jarvis-ai-assistant 0.1.193__py3-none-any.whl → 0.1.195__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.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_agent/__init__.py +45 -41
- jarvis/jarvis_agent/builtin_input_handler.py +26 -4
- jarvis/jarvis_agent/jarvis.py +30 -19
- jarvis/jarvis_agent/main.py +20 -12
- jarvis/jarvis_agent/output_handler.py +7 -7
- jarvis/jarvis_agent/shell_input_handler.py +14 -11
- jarvis/jarvis_code_agent/code_agent.py +81 -79
- jarvis/jarvis_code_agent/lint.py +92 -105
- jarvis/jarvis_code_analysis/checklists/__init__.py +1 -1
- jarvis/jarvis_code_analysis/checklists/c_cpp.py +1 -1
- jarvis/jarvis_code_analysis/checklists/csharp.py +1 -1
- jarvis/jarvis_code_analysis/checklists/data_format.py +1 -1
- jarvis/jarvis_code_analysis/checklists/devops.py +1 -1
- jarvis/jarvis_code_analysis/checklists/docs.py +1 -1
- jarvis/jarvis_code_analysis/checklists/go.py +1 -1
- jarvis/jarvis_code_analysis/checklists/infrastructure.py +1 -1
- jarvis/jarvis_code_analysis/checklists/java.py +1 -1
- jarvis/jarvis_code_analysis/checklists/javascript.py +1 -1
- jarvis/jarvis_code_analysis/checklists/kotlin.py +1 -1
- jarvis/jarvis_code_analysis/checklists/loader.py +31 -29
- jarvis/jarvis_code_analysis/checklists/php.py +1 -1
- jarvis/jarvis_code_analysis/checklists/python.py +1 -1
- jarvis/jarvis_code_analysis/checklists/ruby.py +1 -1
- jarvis/jarvis_code_analysis/checklists/rust.py +1 -1
- jarvis/jarvis_code_analysis/checklists/shell.py +1 -1
- jarvis/jarvis_code_analysis/checklists/sql.py +1 -1
- jarvis/jarvis_code_analysis/checklists/swift.py +1 -1
- jarvis/jarvis_code_analysis/checklists/web.py +1 -1
- jarvis/jarvis_code_analysis/code_review.py +292 -190
- jarvis/jarvis_dev/main.py +73 -56
- jarvis/jarvis_git_details/main.py +29 -33
- jarvis/jarvis_git_squash/main.py +13 -11
- jarvis/jarvis_git_utils/git_commiter.py +15 -5
- jarvis/jarvis_mcp/__init__.py +8 -10
- jarvis/jarvis_mcp/sse_mcp_client.py +182 -205
- jarvis/jarvis_mcp/stdio_mcp_client.py +93 -120
- jarvis/jarvis_mcp/streamable_mcp_client.py +117 -142
- jarvis/jarvis_methodology/main.py +71 -39
- jarvis/jarvis_multi_agent/__init__.py +24 -16
- jarvis/jarvis_multi_agent/main.py +10 -4
- jarvis/jarvis_platform/__init__.py +1 -1
- jarvis/jarvis_platform/base.py +44 -18
- jarvis/jarvis_platform/human.py +15 -3
- jarvis/jarvis_platform/kimi.py +117 -81
- jarvis/jarvis_platform/openai.py +23 -28
- jarvis/jarvis_platform/registry.py +43 -29
- jarvis/jarvis_platform/tongyi.py +16 -10
- jarvis/jarvis_platform/yuanbao.py +197 -144
- jarvis/jarvis_platform_manager/main.py +4 -2
- jarvis/jarvis_smart_shell/main.py +35 -30
- jarvis/jarvis_tools/ask_user.py +8 -16
- jarvis/jarvis_tools/base.py +3 -2
- jarvis/jarvis_tools/chdir.py +7 -19
- jarvis/jarvis_tools/cli/main.py +14 -10
- jarvis/jarvis_tools/code_plan.py +10 -31
- jarvis/jarvis_tools/create_code_agent.py +6 -11
- jarvis/jarvis_tools/create_sub_agent.py +10 -22
- jarvis/jarvis_tools/edit_file.py +98 -76
- jarvis/jarvis_tools/execute_script.py +46 -46
- jarvis/jarvis_tools/file_analyzer.py +22 -34
- jarvis/jarvis_tools/file_operation.py +69 -62
- jarvis/jarvis_tools/generate_new_tool.py +0 -2
- jarvis/jarvis_tools/methodology.py +19 -23
- jarvis/jarvis_tools/read_code.py +35 -35
- jarvis/jarvis_tools/read_webpage.py +7 -16
- jarvis/jarvis_tools/registry.py +63 -30
- jarvis/jarvis_tools/rewrite_file.py +26 -29
- jarvis/jarvis_tools/search_web.py +5 -8
- jarvis/jarvis_tools/virtual_tty.py +133 -122
- jarvis/jarvis_utils/__init__.py +0 -1
- jarvis/jarvis_utils/builtin_replace_map.py +9 -9
- jarvis/jarvis_utils/config.py +60 -37
- jarvis/jarvis_utils/embedding.py +24 -19
- jarvis/jarvis_utils/file_processors.py +16 -9
- jarvis/jarvis_utils/git_utils.py +157 -107
- jarvis/jarvis_utils/globals.py +1 -1
- jarvis/jarvis_utils/input.py +85 -52
- jarvis/jarvis_utils/jarvis_history.py +43 -0
- jarvis/jarvis_utils/methodology.py +31 -24
- jarvis/jarvis_utils/output.py +164 -80
- jarvis/jarvis_utils/tag.py +2 -1
- jarvis/jarvis_utils/utils.py +84 -52
- {jarvis_ai_assistant-0.1.193.dist-info → jarvis_ai_assistant-0.1.195.dist-info}/METADATA +362 -230
- jarvis_ai_assistant-0.1.195.dist-info/RECORD +98 -0
- jarvis/jarvis_agent/file_input_handler.py +0 -112
- jarvis/jarvis_event/__init__.py +0 -0
- jarvis_ai_assistant-0.1.193.dist-info/RECORD +0 -99
- {jarvis_ai_assistant-0.1.193.dist-info → jarvis_ai_assistant-0.1.195.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.193.dist-info → jarvis_ai_assistant-0.1.195.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.193.dist-info → jarvis_ai_assistant-0.1.195.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.193.dist-info → jarvis_ai_assistant-0.1.195.dist-info}/top_level.txt +0 -0
@@ -12,42 +12,45 @@ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
12
12
|
|
13
13
|
class StreamableMcpClient(McpClient):
|
14
14
|
"""Streamable HTTP MCP客户端实现
|
15
|
-
|
15
|
+
|
16
16
|
参数:
|
17
17
|
config: 配置字典,包含以下字段:
|
18
18
|
- base_url: str - MCP服务器的基础URL
|
19
19
|
- auth_token: str - 认证令牌(可选)
|
20
20
|
- headers: Dict[str, str] - 额外的HTTP头(可选)
|
21
21
|
"""
|
22
|
+
|
22
23
|
def __init__(self, config: Dict[str, Any]):
|
23
24
|
self.config = config
|
24
|
-
self.base_url = config.get(
|
25
|
+
self.base_url = config.get("base_url", "")
|
25
26
|
if not self.base_url:
|
26
|
-
raise ValueError(
|
27
|
-
|
27
|
+
raise ValueError("No base_url specified in config")
|
28
|
+
|
28
29
|
# 设置HTTP客户端
|
29
30
|
self.session = requests.Session()
|
30
|
-
self.session.headers.update(
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
self.session.headers.update(
|
32
|
+
{
|
33
|
+
"Content-Type": "application/json",
|
34
|
+
"Accept": "application/json",
|
35
|
+
}
|
36
|
+
)
|
37
|
+
|
35
38
|
# 添加认证令牌(如果提供)
|
36
|
-
auth_token = config.get(
|
39
|
+
auth_token = config.get("auth_token")
|
37
40
|
if auth_token:
|
38
|
-
self.session.headers[
|
39
|
-
|
41
|
+
self.session.headers["Authorization"] = f"Bearer {auth_token}"
|
42
|
+
|
40
43
|
# 添加额外的HTTP头
|
41
|
-
extra_headers = config.get(
|
44
|
+
extra_headers = config.get("headers", {})
|
42
45
|
self.session.headers.update(extra_headers)
|
43
|
-
|
46
|
+
|
44
47
|
# 请求相关属性
|
45
48
|
self.pending_requests = {} # 存储等待响应的请求 {id: Event}
|
46
|
-
self.request_results = {}
|
49
|
+
self.request_results = {} # 存储请求结果 {id: result}
|
47
50
|
self.notification_handlers = {}
|
48
51
|
self.event_lock = threading.Lock()
|
49
52
|
self.request_id_counter = 0
|
50
|
-
|
53
|
+
|
51
54
|
# 初始化连接
|
52
55
|
self._initialize()
|
53
56
|
|
@@ -55,22 +58,24 @@ class StreamableMcpClient(McpClient):
|
|
55
58
|
"""初始化MCP连接"""
|
56
59
|
try:
|
57
60
|
# 发送初始化请求
|
58
|
-
response = self._send_request(
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
61
|
+
response = self._send_request(
|
62
|
+
"initialize",
|
63
|
+
{
|
64
|
+
"processId": None, # 远程客户端不需要进程ID
|
65
|
+
"clientInfo": {"name": "jarvis", "version": "1.0.0"},
|
66
|
+
"capabilities": {},
|
67
|
+
"protocolVersion": "2025-03-26",
|
63
68
|
},
|
64
|
-
|
65
|
-
'protocolVersion': "2025-03-26"
|
66
|
-
})
|
69
|
+
)
|
67
70
|
|
68
71
|
# 验证服务器响应
|
69
|
-
if
|
70
|
-
raise RuntimeError(
|
72
|
+
if "result" not in response:
|
73
|
+
raise RuntimeError(
|
74
|
+
f"初始化失败: {response.get('error', 'Unknown error')}"
|
75
|
+
)
|
71
76
|
|
72
77
|
# 发送initialized通知
|
73
|
-
self._send_notification(
|
78
|
+
self._send_notification("notifications/initialized", {})
|
74
79
|
|
75
80
|
except Exception as e:
|
76
81
|
PrettyOutput.print(f"MCP初始化失败: {str(e)}", OutputType.ERROR)
|
@@ -78,7 +83,7 @@ class StreamableMcpClient(McpClient):
|
|
78
83
|
|
79
84
|
def register_notification_handler(self, method: str, handler: Callable) -> None:
|
80
85
|
"""注册通知处理器
|
81
|
-
|
86
|
+
|
82
87
|
参数:
|
83
88
|
method: 通知方法名
|
84
89
|
handler: 处理通知的回调函数,接收params参数
|
@@ -90,7 +95,7 @@ class StreamableMcpClient(McpClient):
|
|
90
95
|
|
91
96
|
def unregister_notification_handler(self, method: str, handler: Callable) -> None:
|
92
97
|
"""注销通知处理器
|
93
|
-
|
98
|
+
|
94
99
|
参数:
|
95
100
|
method: 通知方法名
|
96
101
|
handler: 要注销的处理器函数
|
@@ -110,38 +115,36 @@ class StreamableMcpClient(McpClient):
|
|
110
115
|
|
111
116
|
def _send_request(self, method: str, params: Dict[str, Any]) -> Dict[str, Any]:
|
112
117
|
"""发送请求到MCP服务器
|
113
|
-
|
118
|
+
|
114
119
|
参数:
|
115
120
|
method: 请求方法
|
116
121
|
params: 请求参数
|
117
|
-
|
122
|
+
|
118
123
|
返回:
|
119
124
|
Dict[str, Any]: 响应结果
|
120
125
|
"""
|
121
126
|
# 生成唯一请求ID
|
122
127
|
req_id = self._get_next_request_id()
|
123
|
-
|
128
|
+
|
124
129
|
# 创建事件标志,用于等待响应
|
125
130
|
event = threading.Event()
|
126
|
-
|
131
|
+
|
127
132
|
with self.event_lock:
|
128
133
|
self.pending_requests[req_id] = event
|
129
|
-
|
134
|
+
|
130
135
|
try:
|
131
136
|
# 构建请求
|
132
137
|
request = {
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
138
|
+
"jsonrpc": "2.0",
|
139
|
+
"method": method,
|
140
|
+
"params": params,
|
141
|
+
"id": req_id,
|
137
142
|
}
|
138
143
|
|
139
144
|
# 发送请求到Streamable HTTP端点
|
140
|
-
mcp_url = urljoin(self.base_url,
|
145
|
+
mcp_url = urljoin(self.base_url, "mcp")
|
141
146
|
response = self.session.post(
|
142
|
-
mcp_url,
|
143
|
-
json=request,
|
144
|
-
stream=True # 启用流式传输
|
147
|
+
mcp_url, json=request, stream=True # 启用流式传输
|
145
148
|
)
|
146
149
|
response.raise_for_status()
|
147
150
|
|
@@ -151,22 +154,22 @@ class StreamableMcpClient(McpClient):
|
|
151
154
|
if line:
|
152
155
|
try:
|
153
156
|
data = json.loads(line)
|
154
|
-
if
|
157
|
+
if "id" in data and data["id"] == req_id:
|
155
158
|
# 这是我们的请求响应
|
156
159
|
result = data
|
157
160
|
break
|
158
|
-
elif
|
161
|
+
elif "method" in data:
|
159
162
|
# 这是一个通知
|
160
|
-
method = data.get(
|
161
|
-
params = data.get(
|
163
|
+
method = data.get("method", "")
|
164
|
+
params = data.get("params", {})
|
162
165
|
if method in self.notification_handlers:
|
163
166
|
for handler in self.notification_handlers[method]:
|
164
167
|
try:
|
165
168
|
handler(params)
|
166
169
|
except Exception as e:
|
167
170
|
PrettyOutput.print(
|
168
|
-
f"处理通知时出错 ({method}): {e}",
|
169
|
-
OutputType.ERROR
|
171
|
+
f"处理通知时出错 ({method}): {e}",
|
172
|
+
OutputType.ERROR,
|
170
173
|
)
|
171
174
|
except json.JSONDecodeError:
|
172
175
|
PrettyOutput.print(f"无法解析响应: {line}", OutputType.WARNING)
|
@@ -188,25 +191,18 @@ class StreamableMcpClient(McpClient):
|
|
188
191
|
|
189
192
|
def _send_notification(self, method: str, params: Dict[str, Any]) -> None:
|
190
193
|
"""发送通知到MCP服务器(不需要响应)
|
191
|
-
|
194
|
+
|
192
195
|
参数:
|
193
196
|
method: 通知方法
|
194
197
|
params: 通知参数
|
195
198
|
"""
|
196
199
|
try:
|
197
200
|
# 构建通知
|
198
|
-
notification = {
|
199
|
-
'jsonrpc': '2.0',
|
200
|
-
'method': method,
|
201
|
-
'params': params
|
202
|
-
}
|
201
|
+
notification = {"jsonrpc": "2.0", "method": method, "params": params}
|
203
202
|
|
204
203
|
# 发送通知到Streamable HTTP端点
|
205
|
-
mcp_url = urljoin(self.base_url,
|
206
|
-
response = self.session.post(
|
207
|
-
mcp_url,
|
208
|
-
json=notification
|
209
|
-
)
|
204
|
+
mcp_url = urljoin(self.base_url, "mcp")
|
205
|
+
response = self.session.post(mcp_url, json=notification)
|
210
206
|
response.raise_for_status()
|
211
207
|
|
212
208
|
except Exception as e:
|
@@ -215,7 +211,7 @@ class StreamableMcpClient(McpClient):
|
|
215
211
|
|
216
212
|
def get_tool_list(self) -> List[Dict[str, Any]]:
|
217
213
|
"""获取工具列表
|
218
|
-
|
214
|
+
|
219
215
|
返回:
|
220
216
|
List[Dict[str, Any]]: 工具列表,每个工具包含以下字段:
|
221
217
|
- name: str - 工具名称
|
@@ -223,34 +219,36 @@ class StreamableMcpClient(McpClient):
|
|
223
219
|
- parameters: Dict - 工具参数
|
224
220
|
"""
|
225
221
|
try:
|
226
|
-
response = self._send_request(
|
227
|
-
if
|
222
|
+
response = self._send_request("tools/list", {})
|
223
|
+
if "result" in response and "tools" in response["result"]:
|
228
224
|
# 注意这里: 响应结构是 response['result']['tools']
|
229
|
-
tools = response[
|
225
|
+
tools = response["result"]["tools"]
|
230
226
|
# 将MCP协议字段转换为内部格式
|
231
227
|
formatted_tools = []
|
232
228
|
for tool in tools:
|
233
229
|
# 从inputSchema中提取参数定义
|
234
|
-
input_schema = tool.get(
|
230
|
+
input_schema = tool.get("inputSchema", {})
|
235
231
|
parameters = {}
|
236
|
-
if
|
237
|
-
parameters = input_schema[
|
238
|
-
|
239
|
-
formatted_tools.append(
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
232
|
+
if "properties" in input_schema:
|
233
|
+
parameters = input_schema["properties"]
|
234
|
+
|
235
|
+
formatted_tools.append(
|
236
|
+
{
|
237
|
+
"name": tool.get("name", ""),
|
238
|
+
"description": tool.get("description", ""),
|
239
|
+
"parameters": parameters,
|
240
|
+
}
|
241
|
+
)
|
244
242
|
return formatted_tools
|
245
243
|
else:
|
246
244
|
error_msg = "获取工具列表失败"
|
247
|
-
if
|
245
|
+
if "error" in response:
|
248
246
|
error_msg += f": {response['error']}"
|
249
|
-
elif
|
247
|
+
elif "result" in response:
|
250
248
|
error_msg += f": 响应格式不正确 - {response['result']}"
|
251
249
|
else:
|
252
250
|
error_msg += ": 未知错误"
|
253
|
-
|
251
|
+
|
254
252
|
PrettyOutput.print(error_msg, OutputType.ERROR)
|
255
253
|
return []
|
256
254
|
except Exception as e:
|
@@ -259,11 +257,11 @@ class StreamableMcpClient(McpClient):
|
|
259
257
|
|
260
258
|
def execute(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
|
261
259
|
"""执行工具
|
262
|
-
|
260
|
+
|
263
261
|
参数:
|
264
262
|
tool_name: 工具名称
|
265
263
|
arguments: 参数字典,包含工具执行所需的参数
|
266
|
-
|
264
|
+
|
267
265
|
返回:
|
268
266
|
Dict[str, Any]: 执行结果,包含以下字段:
|
269
267
|
- success: bool - 是否执行成功
|
@@ -271,43 +269,34 @@ class StreamableMcpClient(McpClient):
|
|
271
269
|
- stderr: str - 标准错误
|
272
270
|
"""
|
273
271
|
try:
|
274
|
-
response = self._send_request(
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
result = response['result']
|
272
|
+
response = self._send_request(
|
273
|
+
"tools/call", {"name": tool_name, "arguments": arguments}
|
274
|
+
)
|
275
|
+
if "result" in response:
|
276
|
+
result = response["result"]
|
280
277
|
# 从content中提取输出信息
|
281
|
-
stdout =
|
282
|
-
stderr =
|
283
|
-
for content in result.get(
|
284
|
-
if content.get(
|
285
|
-
stdout += content.get(
|
286
|
-
elif content.get(
|
287
|
-
stderr += content.get(
|
288
|
-
|
289
|
-
return {
|
290
|
-
'success': True,
|
291
|
-
'stdout': stdout,
|
292
|
-
'stderr': stderr
|
293
|
-
}
|
278
|
+
stdout = ""
|
279
|
+
stderr = ""
|
280
|
+
for content in result.get("content", []):
|
281
|
+
if content.get("type") == "text":
|
282
|
+
stdout += content.get("text", "")
|
283
|
+
elif content.get("type") == "error":
|
284
|
+
stderr += content.get("text", "")
|
285
|
+
|
286
|
+
return {"success": True, "stdout": stdout, "stderr": stderr}
|
294
287
|
else:
|
295
288
|
return {
|
296
|
-
|
297
|
-
|
298
|
-
|
289
|
+
"success": False,
|
290
|
+
"stdout": "",
|
291
|
+
"stderr": response.get("error", "Unknown error"),
|
299
292
|
}
|
300
293
|
except Exception as e:
|
301
294
|
PrettyOutput.print(f"执行工具失败: {str(e)}", OutputType.ERROR)
|
302
|
-
return {
|
303
|
-
'success': False,
|
304
|
-
'stdout': '',
|
305
|
-
'stderr': str(e)
|
306
|
-
}
|
295
|
+
return {"success": False, "stdout": "", "stderr": str(e)}
|
307
296
|
|
308
297
|
def get_resource_list(self) -> List[Dict[str, Any]]:
|
309
298
|
"""获取资源列表
|
310
|
-
|
299
|
+
|
311
300
|
返回:
|
312
301
|
List[Dict[str, Any]]: 资源列表,每个资源包含以下字段:
|
313
302
|
- uri: str - 资源的唯一标识符
|
@@ -316,12 +305,12 @@ class StreamableMcpClient(McpClient):
|
|
316
305
|
- mimeType: str - 资源的MIME类型(可选)
|
317
306
|
"""
|
318
307
|
try:
|
319
|
-
response = self._send_request(
|
320
|
-
if
|
321
|
-
return response[
|
308
|
+
response = self._send_request("resources/list", {})
|
309
|
+
if "result" in response and "resources" in response["result"]:
|
310
|
+
return response["result"]["resources"]
|
322
311
|
else:
|
323
312
|
error_msg = "获取资源列表失败"
|
324
|
-
if
|
313
|
+
if "error" in response:
|
325
314
|
error_msg += f": {response['error']}"
|
326
315
|
else:
|
327
316
|
error_msg += ": 未知错误"
|
@@ -333,10 +322,10 @@ class StreamableMcpClient(McpClient):
|
|
333
322
|
|
334
323
|
def get_resource(self, uri: str) -> Dict[str, Any]:
|
335
324
|
"""获取指定资源的内容
|
336
|
-
|
325
|
+
|
337
326
|
参数:
|
338
327
|
uri: str - 资源的URI标识符
|
339
|
-
|
328
|
+
|
340
329
|
返回:
|
341
330
|
Dict[str, Any]: 执行结果,包含以下字段:
|
342
331
|
- success: bool - 是否执行成功
|
@@ -344,51 +333,37 @@ class StreamableMcpClient(McpClient):
|
|
344
333
|
- stderr: str - 错误信息
|
345
334
|
"""
|
346
335
|
try:
|
347
|
-
response = self._send_request(
|
348
|
-
|
349
|
-
|
350
|
-
if 'result' in response and 'contents' in response['result']:
|
351
|
-
contents = response['result']['contents']
|
336
|
+
response = self._send_request("resources/read", {"uri": uri})
|
337
|
+
if "result" in response and "contents" in response["result"]:
|
338
|
+
contents = response["result"]["contents"]
|
352
339
|
if contents:
|
353
340
|
content = contents[0] # 获取第一个资源内容
|
354
341
|
# 根据资源类型返回内容
|
355
|
-
if
|
342
|
+
if "text" in content:
|
356
343
|
return {
|
357
|
-
|
358
|
-
|
359
|
-
|
344
|
+
"success": True,
|
345
|
+
"stdout": content["text"],
|
346
|
+
"stderr": "",
|
360
347
|
}
|
361
|
-
elif
|
348
|
+
elif "blob" in content:
|
362
349
|
return {
|
363
|
-
|
364
|
-
|
365
|
-
|
350
|
+
"success": True,
|
351
|
+
"stdout": content["blob"],
|
352
|
+
"stderr": "",
|
366
353
|
}
|
367
|
-
return {
|
368
|
-
'success': False,
|
369
|
-
'stdout': '',
|
370
|
-
'stderr': '资源内容为空'
|
371
|
-
}
|
354
|
+
return {"success": False, "stdout": "", "stderr": "资源内容为空"}
|
372
355
|
else:
|
373
356
|
error_msg = "获取资源内容失败"
|
374
|
-
if
|
357
|
+
if "error" in response:
|
375
358
|
error_msg += f": {response['error']}"
|
376
359
|
else:
|
377
360
|
error_msg += ": 未知错误"
|
378
361
|
PrettyOutput.print(error_msg, OutputType.ERROR)
|
379
|
-
return {
|
380
|
-
'success': False,
|
381
|
-
'stdout': '',
|
382
|
-
'stderr': error_msg
|
383
|
-
}
|
362
|
+
return {"success": False, "stdout": "", "stderr": error_msg}
|
384
363
|
except Exception as e:
|
385
364
|
error_msg = f"获取资源内容失败: {str(e)}"
|
386
365
|
PrettyOutput.print(error_msg, OutputType.ERROR)
|
387
|
-
return {
|
388
|
-
'success': False,
|
389
|
-
'stdout': '',
|
390
|
-
'stderr': error_msg
|
391
|
-
}
|
366
|
+
return {"success": False, "stdout": "", "stderr": error_msg}
|
392
367
|
|
393
368
|
def __del__(self):
|
394
369
|
"""清理资源"""
|
@@ -398,7 +373,7 @@ class StreamableMcpClient(McpClient):
|
|
398
373
|
event.set() # 释放所有等待的请求
|
399
374
|
self.pending_requests.clear()
|
400
375
|
self.request_results.clear()
|
401
|
-
|
376
|
+
|
402
377
|
# 关闭HTTP会话
|
403
378
|
if self.session:
|
404
|
-
self.session.close()
|
379
|
+
self.session.close()
|