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.
- chuk_tool_processor/core/__init__.py +1 -1
- chuk_tool_processor/core/exceptions.py +10 -4
- chuk_tool_processor/core/processor.py +97 -97
- chuk_tool_processor/execution/strategies/inprocess_strategy.py +142 -150
- chuk_tool_processor/execution/strategies/subprocess_strategy.py +200 -205
- chuk_tool_processor/execution/tool_executor.py +82 -84
- chuk_tool_processor/execution/wrappers/caching.py +102 -103
- chuk_tool_processor/execution/wrappers/rate_limiting.py +45 -42
- chuk_tool_processor/execution/wrappers/retry.py +23 -25
- chuk_tool_processor/logging/__init__.py +23 -17
- chuk_tool_processor/logging/context.py +40 -45
- chuk_tool_processor/logging/formatter.py +22 -21
- chuk_tool_processor/logging/helpers.py +24 -38
- chuk_tool_processor/logging/metrics.py +11 -13
- chuk_tool_processor/mcp/__init__.py +8 -12
- chuk_tool_processor/mcp/mcp_tool.py +124 -112
- chuk_tool_processor/mcp/register_mcp_tools.py +17 -17
- chuk_tool_processor/mcp/setup_mcp_http_streamable.py +11 -13
- chuk_tool_processor/mcp/setup_mcp_sse.py +11 -13
- chuk_tool_processor/mcp/setup_mcp_stdio.py +7 -9
- chuk_tool_processor/mcp/stream_manager.py +168 -204
- chuk_tool_processor/mcp/transport/__init__.py +4 -4
- chuk_tool_processor/mcp/transport/base_transport.py +43 -58
- chuk_tool_processor/mcp/transport/http_streamable_transport.py +145 -163
- chuk_tool_processor/mcp/transport/sse_transport.py +217 -255
- chuk_tool_processor/mcp/transport/stdio_transport.py +171 -189
- chuk_tool_processor/models/__init__.py +1 -1
- chuk_tool_processor/models/execution_strategy.py +16 -21
- chuk_tool_processor/models/streaming_tool.py +28 -25
- chuk_tool_processor/models/tool_call.py +19 -34
- chuk_tool_processor/models/tool_export_mixin.py +22 -8
- chuk_tool_processor/models/tool_result.py +40 -77
- chuk_tool_processor/models/validated_tool.py +14 -16
- chuk_tool_processor/plugins/__init__.py +1 -1
- chuk_tool_processor/plugins/discovery.py +10 -10
- chuk_tool_processor/plugins/parsers/__init__.py +1 -1
- chuk_tool_processor/plugins/parsers/base.py +1 -2
- chuk_tool_processor/plugins/parsers/function_call_tool.py +13 -8
- chuk_tool_processor/plugins/parsers/json_tool.py +4 -3
- chuk_tool_processor/plugins/parsers/openai_tool.py +12 -7
- chuk_tool_processor/plugins/parsers/xml_tool.py +4 -4
- chuk_tool_processor/registry/__init__.py +12 -12
- chuk_tool_processor/registry/auto_register.py +22 -30
- chuk_tool_processor/registry/decorators.py +127 -129
- chuk_tool_processor/registry/interface.py +26 -23
- chuk_tool_processor/registry/metadata.py +27 -22
- chuk_tool_processor/registry/provider.py +17 -18
- chuk_tool_processor/registry/providers/__init__.py +16 -19
- chuk_tool_processor/registry/providers/memory.py +18 -25
- chuk_tool_processor/registry/tool_export.py +42 -51
- chuk_tool_processor/utils/validation.py +15 -16
- {chuk_tool_processor-0.6.12.dist-info → chuk_tool_processor-0.6.13.dist-info}/METADATA +1 -1
- chuk_tool_processor-0.6.13.dist-info/RECORD +60 -0
- chuk_tool_processor-0.6.12.dist-info/RECORD +0 -60
- {chuk_tool_processor-0.6.12.dist-info → chuk_tool_processor-0.6.13.dist-info}/WHEEL +0 -0
- {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
|
|
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) ->
|
|
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(
|
|
75
|
-
|
|
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) ->
|
|
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) ->
|
|
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) ->
|
|
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) ->
|
|
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:
|
|
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
|
-
|
|
168
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
234
|
+
if hasattr(self, "url"):
|
|
250
235
|
transport_info = f", url={self.url}" # Fixed: was "url: "
|
|
251
|
-
elif hasattr(self,
|
|
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})"
|