chuk-tool-processor 0.6.12__py3-none-any.whl → 0.6.13__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.

Files changed (56) hide show
  1. chuk_tool_processor/core/__init__.py +1 -1
  2. chuk_tool_processor/core/exceptions.py +10 -4
  3. chuk_tool_processor/core/processor.py +97 -97
  4. chuk_tool_processor/execution/strategies/inprocess_strategy.py +142 -150
  5. chuk_tool_processor/execution/strategies/subprocess_strategy.py +200 -205
  6. chuk_tool_processor/execution/tool_executor.py +82 -84
  7. chuk_tool_processor/execution/wrappers/caching.py +102 -103
  8. chuk_tool_processor/execution/wrappers/rate_limiting.py +45 -42
  9. chuk_tool_processor/execution/wrappers/retry.py +23 -25
  10. chuk_tool_processor/logging/__init__.py +23 -17
  11. chuk_tool_processor/logging/context.py +40 -45
  12. chuk_tool_processor/logging/formatter.py +22 -21
  13. chuk_tool_processor/logging/helpers.py +24 -38
  14. chuk_tool_processor/logging/metrics.py +11 -13
  15. chuk_tool_processor/mcp/__init__.py +8 -12
  16. chuk_tool_processor/mcp/mcp_tool.py +124 -112
  17. chuk_tool_processor/mcp/register_mcp_tools.py +17 -17
  18. chuk_tool_processor/mcp/setup_mcp_http_streamable.py +11 -13
  19. chuk_tool_processor/mcp/setup_mcp_sse.py +11 -13
  20. chuk_tool_processor/mcp/setup_mcp_stdio.py +7 -9
  21. chuk_tool_processor/mcp/stream_manager.py +168 -204
  22. chuk_tool_processor/mcp/transport/__init__.py +4 -4
  23. chuk_tool_processor/mcp/transport/base_transport.py +43 -58
  24. chuk_tool_processor/mcp/transport/http_streamable_transport.py +145 -163
  25. chuk_tool_processor/mcp/transport/sse_transport.py +217 -255
  26. chuk_tool_processor/mcp/transport/stdio_transport.py +171 -189
  27. chuk_tool_processor/models/__init__.py +1 -1
  28. chuk_tool_processor/models/execution_strategy.py +16 -21
  29. chuk_tool_processor/models/streaming_tool.py +28 -25
  30. chuk_tool_processor/models/tool_call.py +19 -34
  31. chuk_tool_processor/models/tool_export_mixin.py +22 -8
  32. chuk_tool_processor/models/tool_result.py +40 -77
  33. chuk_tool_processor/models/validated_tool.py +14 -16
  34. chuk_tool_processor/plugins/__init__.py +1 -1
  35. chuk_tool_processor/plugins/discovery.py +10 -10
  36. chuk_tool_processor/plugins/parsers/__init__.py +1 -1
  37. chuk_tool_processor/plugins/parsers/base.py +1 -2
  38. chuk_tool_processor/plugins/parsers/function_call_tool.py +13 -8
  39. chuk_tool_processor/plugins/parsers/json_tool.py +4 -3
  40. chuk_tool_processor/plugins/parsers/openai_tool.py +12 -7
  41. chuk_tool_processor/plugins/parsers/xml_tool.py +4 -4
  42. chuk_tool_processor/registry/__init__.py +12 -12
  43. chuk_tool_processor/registry/auto_register.py +22 -30
  44. chuk_tool_processor/registry/decorators.py +127 -129
  45. chuk_tool_processor/registry/interface.py +26 -23
  46. chuk_tool_processor/registry/metadata.py +27 -22
  47. chuk_tool_processor/registry/provider.py +17 -18
  48. chuk_tool_processor/registry/providers/__init__.py +16 -19
  49. chuk_tool_processor/registry/providers/memory.py +18 -25
  50. chuk_tool_processor/registry/tool_export.py +42 -51
  51. chuk_tool_processor/utils/validation.py +15 -16
  52. {chuk_tool_processor-0.6.12.dist-info → chuk_tool_processor-0.6.13.dist-info}/METADATA +1 -1
  53. chuk_tool_processor-0.6.13.dist-info/RECORD +60 -0
  54. chuk_tool_processor-0.6.12.dist-info/RECORD +0 -60
  55. {chuk_tool_processor-0.6.12.dist-info → chuk_tool_processor-0.6.13.dist-info}/WHEEL +0 -0
  56. {chuk_tool_processor-0.6.12.dist-info → chuk_tool_processor-0.6.13.dist-info}/top_level.txt +0 -0
@@ -10,13 +10,13 @@ All transports now follow the same interface and provide consistent behavior:
10
10
  """
11
11
 
12
12
  from .base_transport import MCPBaseTransport
13
- from .stdio_transport import StdioTransport
14
- from .sse_transport import SSETransport
15
13
  from .http_streamable_transport import HTTPStreamableTransport
14
+ from .sse_transport import SSETransport
15
+ from .stdio_transport import StdioTransport
16
16
 
17
17
  __all__ = [
18
18
  "MCPBaseTransport",
19
19
  "StdioTransport",
20
- "SSETransport",
20
+ "SSETransport",
21
21
  "HTTPStreamableTransport",
22
- ]
22
+ ]
@@ -2,16 +2,17 @@
2
2
  """
3
3
  Abstract base class for MCP transports with complete interface definition.
4
4
  """
5
+
5
6
  from __future__ import annotations
6
7
 
7
8
  from abc import ABC, abstractmethod
8
- from typing import Any, Dict, List, Optional
9
+ from typing import Any
9
10
 
10
11
 
11
12
  class MCPBaseTransport(ABC):
12
13
  """
13
14
  Abstract base class for all MCP transport implementations.
14
-
15
+
15
16
  Defines the complete interface that all transports must implement
16
17
  for consistency across stdio, SSE, and HTTP streamable transports.
17
18
  """
@@ -23,7 +24,7 @@ class MCPBaseTransport(ABC):
23
24
  async def initialize(self) -> bool:
24
25
  """
25
26
  Initialize the transport connection.
26
-
27
+
27
28
  Returns:
28
29
  True if initialization was successful, False otherwise.
29
30
  """
@@ -41,7 +42,7 @@ class MCPBaseTransport(ABC):
41
42
  async def send_ping(self) -> bool:
42
43
  """
43
44
  Send a ping to verify the connection is alive.
44
-
45
+
45
46
  Returns:
46
47
  True if ping was successful, False otherwise.
47
48
  """
@@ -51,7 +52,7 @@ class MCPBaseTransport(ABC):
51
52
  def is_connected(self) -> bool:
52
53
  """
53
54
  Check if the transport is connected and ready for operations.
54
-
55
+
55
56
  Returns:
56
57
  True if connected, False otherwise.
57
58
  """
@@ -61,46 +62,47 @@ class MCPBaseTransport(ABC):
61
62
  # Core MCP operations #
62
63
  # ------------------------------------------------------------------ #
63
64
  @abstractmethod
64
- async def get_tools(self) -> List[Dict[str, Any]]:
65
+ async def get_tools(self) -> list[dict[str, Any]]:
65
66
  """
66
67
  Get the list of available tools from the server.
67
-
68
+
68
69
  Returns:
69
70
  List of tool definitions.
70
71
  """
71
72
  pass
72
73
 
73
74
  @abstractmethod
74
- async def call_tool(self, tool_name: str, arguments: Dict[str, Any],
75
- timeout: Optional[float] = None) -> Dict[str, Any]:
75
+ async def call_tool(
76
+ self, tool_name: str, arguments: dict[str, Any], timeout: float | None = None
77
+ ) -> dict[str, Any]:
76
78
  """
77
79
  Call a tool with the given arguments.
78
-
80
+
79
81
  Args:
80
82
  tool_name: Name of the tool to call
81
83
  arguments: Arguments to pass to the tool
82
84
  timeout: Optional timeout for the operation
83
-
85
+
84
86
  Returns:
85
87
  Dictionary with 'isError' boolean and either 'content' or 'error'
86
88
  """
87
89
  pass
88
90
 
89
91
  @abstractmethod
90
- async def list_resources(self) -> Dict[str, Any]:
92
+ async def list_resources(self) -> dict[str, Any]:
91
93
  """
92
94
  List available resources from the server.
93
-
95
+
94
96
  Returns:
95
97
  Dictionary containing resources list or empty dict if not supported.
96
98
  """
97
99
  pass
98
100
 
99
101
  @abstractmethod
100
- async def list_prompts(self) -> Dict[str, Any]:
102
+ async def list_prompts(self) -> dict[str, Any]:
101
103
  """
102
104
  List available prompts from the server.
103
-
105
+
104
106
  Returns:
105
107
  Dictionary containing prompts list or empty dict if not supported.
106
108
  """
@@ -110,10 +112,10 @@ class MCPBaseTransport(ABC):
110
112
  # Metrics and monitoring (all transports should support these) #
111
113
  # ------------------------------------------------------------------ #
112
114
  @abstractmethod
113
- def get_metrics(self) -> Dict[str, Any]:
115
+ def get_metrics(self) -> dict[str, Any]:
114
116
  """
115
117
  Get performance and connection metrics.
116
-
118
+
117
119
  Returns:
118
120
  Dictionary containing metrics data.
119
121
  """
@@ -127,10 +129,10 @@ class MCPBaseTransport(ABC):
127
129
  # ------------------------------------------------------------------ #
128
130
  # Backward compatibility and utility methods #
129
131
  # ------------------------------------------------------------------ #
130
- def get_streams(self) -> List[tuple]:
132
+ def get_streams(self) -> list[tuple]:
131
133
  """
132
134
  Get underlying stream objects for backward compatibility.
133
-
135
+
134
136
  Returns:
135
137
  List of (read_stream, write_stream) tuples, empty if not applicable.
136
138
  """
@@ -153,64 +155,46 @@ class MCPBaseTransport(ABC):
153
155
  # ------------------------------------------------------------------ #
154
156
  # Shared helper methods for response normalization #
155
157
  # ------------------------------------------------------------------ #
156
- def _normalize_mcp_response(self, response: Dict[str, Any]) -> Dict[str, Any]:
158
+ def _normalize_mcp_response(self, response: dict[str, Any]) -> dict[str, Any]:
157
159
  """
158
160
  Normalize MCP response to consistent format.
159
-
161
+
160
162
  This provides shared logic for all transports to ensure consistent
161
163
  response format regardless of transport type.
162
164
  """
163
165
  # Handle explicit error in response
164
166
  if "error" in response:
165
167
  error_info = response["error"]
166
- if isinstance(error_info, dict):
167
- error_msg = error_info.get("message", "Unknown error")
168
- else:
169
- error_msg = str(error_info)
170
-
171
- return {
172
- "isError": True,
173
- "error": error_msg
174
- }
168
+ error_msg = error_info.get("message", "Unknown error") if isinstance(error_info, dict) else str(error_info)
169
+
170
+ return {"isError": True, "error": error_msg}
175
171
 
176
172
  # Handle successful response with result
177
173
  if "result" in response:
178
174
  result = response["result"]
179
-
175
+
180
176
  if isinstance(result, dict) and "content" in result:
181
- return {
182
- "isError": False,
183
- "content": self._extract_mcp_content(result["content"])
184
- }
177
+ return {"isError": False, "content": self._extract_mcp_content(result["content"])}
185
178
  else:
186
- return {
187
- "isError": False,
188
- "content": result
189
- }
179
+ return {"isError": False, "content": result}
190
180
 
191
181
  # Handle direct content-based response
192
182
  if "content" in response:
193
- return {
194
- "isError": False,
195
- "content": self._extract_mcp_content(response["content"])
196
- }
183
+ return {"isError": False, "content": self._extract_mcp_content(response["content"])}
197
184
 
198
185
  # Fallback
199
- return {
200
- "isError": False,
201
- "content": response
202
- }
186
+ return {"isError": False, "content": response}
203
187
 
204
188
  def _extract_mcp_content(self, content_list: Any) -> Any:
205
189
  """
206
190
  Extract content from MCP content format.
207
-
191
+
208
192
  Handles the standard MCP content format where content is a list
209
193
  of content items with type and data.
210
194
  """
211
195
  if not isinstance(content_list, list) or not content_list:
212
196
  return content_list
213
-
197
+
214
198
  # Handle single content item
215
199
  if len(content_list) == 1:
216
200
  content_item = content_list[0]
@@ -220,12 +204,13 @@ class MCPBaseTransport(ABC):
220
204
  # Try to parse JSON, fall back to plain text
221
205
  try:
222
206
  import json
207
+
223
208
  return json.loads(text_content)
224
209
  except json.JSONDecodeError:
225
210
  return text_content
226
211
  else:
227
212
  return content_item
228
-
213
+
229
214
  # Multiple content items - return as-is
230
215
  return content_list
231
216
 
@@ -234,21 +219,21 @@ class MCPBaseTransport(ABC):
234
219
  # ------------------------------------------------------------------ #
235
220
  def __repr__(self) -> str:
236
221
  """Standard string representation for all transports."""
237
- status = "initialized" if getattr(self, '_initialized', False) else "not initialized"
238
-
222
+ status = "initialized" if getattr(self, "_initialized", False) else "not initialized"
223
+
239
224
  # Add metrics info if available
240
225
  metrics_info = ""
241
- if hasattr(self, 'enable_metrics') and getattr(self, 'enable_metrics', False):
226
+ if hasattr(self, "enable_metrics") and getattr(self, "enable_metrics", False):
242
227
  metrics = self.get_metrics()
243
228
  if metrics.get("total_calls", 0) > 0:
244
229
  success_rate = (metrics.get("successful_calls", 0) / metrics["total_calls"]) * 100
245
230
  metrics_info = f", calls: {metrics['total_calls']}, success: {success_rate:.1f}%"
246
-
231
+
247
232
  # Add transport-specific info - FIXED FORMAT
248
233
  transport_info = ""
249
- if hasattr(self, 'url'):
234
+ if hasattr(self, "url"):
250
235
  transport_info = f", url={self.url}" # Fixed: was "url: "
251
- elif hasattr(self, 'server_params') and hasattr(self.server_params, 'command'):
236
+ elif hasattr(self, "server_params") and hasattr(self.server_params, "command"):
252
237
  transport_info = f", command={self.server_params.command}" # Fixed: was "command: "
253
-
254
- return f"{self.__class__.__name__}(status={status}{transport_info}{metrics_info})"
238
+
239
+ return f"{self.__class__.__name__}(status={status}{transport_info}{metrics_info})"