auto-coder 0.1.334__py3-none-any.whl → 0.1.340__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 auto-coder might be problematic. Click here for more details.

Files changed (70) hide show
  1. {auto_coder-0.1.334.dist-info → auto_coder-0.1.340.dist-info}/METADATA +2 -2
  2. {auto_coder-0.1.334.dist-info → auto_coder-0.1.340.dist-info}/RECORD +70 -34
  3. autocoder/agent/agentic_edit.py +833 -0
  4. autocoder/agent/agentic_edit_tools/__init__.py +28 -0
  5. autocoder/agent/agentic_edit_tools/ask_followup_question_tool_resolver.py +32 -0
  6. autocoder/agent/agentic_edit_tools/attempt_completion_tool_resolver.py +29 -0
  7. autocoder/agent/agentic_edit_tools/base_tool_resolver.py +29 -0
  8. autocoder/agent/agentic_edit_tools/execute_command_tool_resolver.py +84 -0
  9. autocoder/agent/agentic_edit_tools/list_code_definition_names_tool_resolver.py +75 -0
  10. autocoder/agent/agentic_edit_tools/list_files_tool_resolver.py +62 -0
  11. autocoder/agent/agentic_edit_tools/plan_mode_respond_tool_resolver.py +30 -0
  12. autocoder/agent/agentic_edit_tools/read_file_tool_resolver.py +36 -0
  13. autocoder/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +95 -0
  14. autocoder/agent/agentic_edit_tools/search_files_tool_resolver.py +70 -0
  15. autocoder/agent/agentic_edit_tools/use_mcp_tool_resolver.py +55 -0
  16. autocoder/agent/agentic_edit_tools/write_to_file_tool_resolver.py +98 -0
  17. autocoder/agent/agentic_edit_types.py +124 -0
  18. autocoder/agent/agentic_filter.py +14 -7
  19. autocoder/auto_coder.py +39 -18
  20. autocoder/auto_coder_rag.py +18 -9
  21. autocoder/auto_coder_runner.py +107 -8
  22. autocoder/chat_auto_coder.py +1 -2
  23. autocoder/chat_auto_coder_lang.py +18 -2
  24. autocoder/commands/tools.py +5 -1
  25. autocoder/common/__init__.py +2 -0
  26. autocoder/common/auto_coder_lang.py +84 -8
  27. autocoder/common/code_auto_generate_diff.py +1 -1
  28. autocoder/common/code_auto_generate_editblock.py +1 -1
  29. autocoder/common/code_auto_generate_strict_diff.py +1 -1
  30. autocoder/common/mcp_hub.py +185 -2
  31. autocoder/common/mcp_server.py +243 -306
  32. autocoder/common/mcp_server_install.py +269 -0
  33. autocoder/common/mcp_server_types.py +169 -0
  34. autocoder/common/stream_out_type.py +3 -0
  35. autocoder/common/v2/agent/__init__.py +0 -0
  36. autocoder/common/v2/agent/agentic_edit.py +1433 -0
  37. autocoder/common/v2/agent/agentic_edit_conversation.py +179 -0
  38. autocoder/common/v2/agent/agentic_edit_tools/__init__.py +28 -0
  39. autocoder/common/v2/agent/agentic_edit_tools/ask_followup_question_tool_resolver.py +70 -0
  40. autocoder/common/v2/agent/agentic_edit_tools/attempt_completion_tool_resolver.py +35 -0
  41. autocoder/common/v2/agent/agentic_edit_tools/base_tool_resolver.py +33 -0
  42. autocoder/common/v2/agent/agentic_edit_tools/execute_command_tool_resolver.py +88 -0
  43. autocoder/common/v2/agent/agentic_edit_tools/list_code_definition_names_tool_resolver.py +80 -0
  44. autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py +105 -0
  45. autocoder/common/v2/agent/agentic_edit_tools/plan_mode_respond_tool_resolver.py +35 -0
  46. autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +51 -0
  47. autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +153 -0
  48. autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py +104 -0
  49. autocoder/common/v2/agent/agentic_edit_tools/use_mcp_tool_resolver.py +46 -0
  50. autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py +58 -0
  51. autocoder/common/v2/agent/agentic_edit_types.py +167 -0
  52. autocoder/common/v2/agent/agentic_tool_display.py +184 -0
  53. autocoder/common/v2/code_agentic_editblock_manager.py +812 -0
  54. autocoder/common/v2/code_auto_generate.py +1 -1
  55. autocoder/common/v2/code_auto_generate_diff.py +1 -1
  56. autocoder/common/v2/code_auto_generate_editblock.py +1 -1
  57. autocoder/common/v2/code_auto_generate_strict_diff.py +1 -1
  58. autocoder/common/v2/code_editblock_manager.py +151 -178
  59. autocoder/compilers/provided_compiler.py +3 -2
  60. autocoder/events/event_manager.py +4 -4
  61. autocoder/events/event_types.py +1 -0
  62. autocoder/memory/active_context_manager.py +2 -29
  63. autocoder/models.py +10 -2
  64. autocoder/shadows/shadow_manager.py +1 -1
  65. autocoder/utils/llms.py +4 -2
  66. autocoder/version.py +1 -1
  67. {auto_coder-0.1.334.dist-info → auto_coder-0.1.340.dist-info}/LICENSE +0 -0
  68. {auto_coder-0.1.334.dist-info → auto_coder-0.1.340.dist-info}/WHEEL +0 -0
  69. {auto_coder-0.1.334.dist-info → auto_coder-0.1.340.dist-info}/entry_points.txt +0 -0
  70. {auto_coder-0.1.334.dist-info → auto_coder-0.1.340.dist-info}/top_level.txt +0 -0
@@ -1,111 +1,25 @@
1
1
  import asyncio
2
2
  from asyncio import Queue as AsyncQueue
3
3
  import threading
4
- from typing import List, Dict, Any, Optional
5
- from dataclasses import dataclass
6
- from autocoder.common.mcp_hub import McpHub
7
- from autocoder.common.mcp_tools import McpExecutor
8
- from autocoder.common.mcp_hub import MCP_BUILD_IN_SERVERS
9
- import json
4
+ from typing import List
10
5
  import os
11
6
  import time
12
- from pydantic import BaseModel
13
- import sys
14
7
  from loguru import logger
8
+ import json
9
+
10
+ from autocoder.common.mcp_hub import McpHub, MCP_BUILD_IN_SERVERS, MarketplaceMCPServerItem
11
+ from autocoder.common.mcp_tools import McpExecutor
15
12
  from autocoder.utils.llms import get_single_llm
16
13
  from autocoder.chat_auto_coder_lang import get_message_with_format
17
-
18
- @dataclass
19
- class McpRequest:
20
- query: str
21
- model: Optional[str] = None
22
- product_mode: Optional[str] = None
23
-
24
- @dataclass
25
- class McpInstallRequest:
26
- server_name_or_config: Optional[str] = None
27
-
28
-
29
- @dataclass
30
- class McpRemoveRequest:
31
- server_name: str
32
-
33
-
34
- @dataclass
35
- class McpListRequest:
36
- """Request to list all builtin MCP servers"""
37
- pass
38
-
39
-
40
- @dataclass
41
- class McpListRunningRequest:
42
- """Request to list all running MCP servers"""
43
- pass
44
-
45
- @dataclass
46
- class McpResponse:
47
- result: str
48
- error: Optional[str] = None
49
-
50
-
51
- @dataclass
52
- class McpRefreshRequest:
53
- """Request to refresh MCP server connections"""
54
- name: Optional[str] = None
55
-
56
- @dataclass
57
- class McpServerInfoRequest:
58
- """Request to get MCP server info"""
59
- model: Optional[str] = None
60
- product_mode: Optional[str] = None
61
-
62
-
63
- @dataclass
64
- class McpExternalServer(BaseModel):
65
- result: str
66
- error: Optional[str] = None
67
-
68
-
69
- class McpExternalServer(BaseModel):
70
- """Represents an external MCP server configuration"""
71
- name: str
72
- description: str
73
- vendor: str
74
- sourceUrl: str
75
- homepage: str
76
- license: str
77
- runtime: str
78
-
79
-
80
- def get_mcp_external_servers() -> List[McpExternalServer]:
81
- """Get external MCP servers list from GitHub"""
82
- cache_dir = os.path.join(".auto-coder", "tmp")
83
- os.makedirs(cache_dir, exist_ok=True)
84
- cache_file = os.path.join(cache_dir, "mcp_external_servers.json")
85
-
86
- # Check cache first
87
- if os.path.exists(cache_file):
88
- cache_time = os.path.getmtime(cache_file)
89
- if time.time() - cache_time < 3600: # 1 hour cache
90
- with open(cache_file, "r",encoding="utf-8") as f:
91
- raw_data = json.load(f)
92
- return [McpExternalServer(**item) for item in raw_data]
93
-
94
- # Fetch from GitHub
95
- url = "https://raw.githubusercontent.com/michaellatman/mcp-get/refs/heads/main/packages/package-list.json"
96
- try:
97
- import requests
98
- response = requests.get(url)
99
- if response.status_code == 200:
100
- raw_data = response.json()
101
- with open(cache_file, "w",encoding="utf-8") as f:
102
- json.dump(raw_data, f)
103
- return [McpExternalServer(**item) for item in raw_data]
104
- return []
105
- except Exception as e:
106
- logger.error(f"Failed to fetch external MCP servers: {e}")
107
- return []
108
-
14
+ from autocoder.common.mcp_server_types import (
15
+ McpRequest, McpInstallRequest, McpRemoveRequest, McpListRequest,
16
+ McpListRunningRequest, McpRefreshRequest, McpServerInfoRequest,
17
+ McpResponse, ServerInfo, InstallResult, RemoveResult, ListResult,
18
+ ListRunningResult, RefreshResult, QueryResult, ErrorResult, ServerConfig,StringResult,
19
+ ExternalServerInfo, McpExternalServer, MarketplaceAddRequest, MarketplaceAddResult,
20
+ MarketplaceUpdateRequest, MarketplaceUpdateResult
21
+ )
22
+ from autocoder.common.mcp_server_install import McpServerInstaller
109
23
 
110
24
  class McpServer:
111
25
  def __init__(self):
@@ -114,6 +28,7 @@ class McpServer:
114
28
  self._running = False
115
29
  self._task = None
116
30
  self._loop = None
31
+ self._installer = McpServerInstaller()
117
32
 
118
33
  def start(self):
119
34
  if self._running:
@@ -135,244 +50,143 @@ class McpServer:
135
50
  self._task = self._loop.create_task(self._process_request())
136
51
  self._loop.run_forever()
137
52
 
138
- def _install_python_package(self, package_name: str) -> None:
139
- """Install a Python package using pip"""
140
- try:
141
- import importlib
142
- importlib.import_module(package_name.replace("-", "_"))
143
- except ImportError:
144
- import subprocess
145
- try:
146
- subprocess.run([sys.executable, "-m", "pip", "install", package_name], check=True)
147
- except subprocess.CalledProcessError:
148
- print(f"\n\033[93mFailed to automatically install {package_name}. Please manually install it using:\n")
149
- print(f" pip install {package_name}\n")
150
- print(f"We have already updated the server configuration in ~/.autocoder/mcp/settings.json.\n")
151
- print(f"After installation, you can restart the auto-coder.chat using the server.\033[0m\n")
152
-
153
- def _install_node_package(self, package_name: str) -> None:
154
- """Install a Node.js package using npm"""
155
- import subprocess
156
- try:
157
- subprocess.run(["npx", package_name, "--version"], check=True)
158
- except:
159
- try:
160
- subprocess.run(["npm", "install", "-y", "-g", package_name], check=True)
161
- except subprocess.CalledProcessError:
162
- print(f"\n\033[93mFailed to automatically install {package_name}. Please manually install it using:\n")
163
- print(f" npm install -g {package_name}\n")
164
- print(f"We have already updated the server configuration in ~/.autocoder/mcp/settings.json.\n")
165
- print(f"After installation, you can restart the auto-coder.chat using the server.\033[0m\n")
166
-
167
- def _deep_merge_dicts(self, dict1, dict2):
168
- """
169
- 深度合并两个字典,包括嵌套的字典
170
- dict1是基础字典,dict2是优先字典(当有冲突时保留dict2的值)
171
- """
172
- result = dict1.copy()
173
- for key, value in dict2.items():
174
- if key in result and isinstance(result[key], dict) and isinstance(value, dict):
175
- # 如果两个字典都包含相同的键,并且两个值都是字典,则递归合并
176
- result[key] = self._deep_merge_dicts(result[key], value)
177
- else:
178
- # 否则,使用dict2的值覆盖或添加到结果
179
- result[key] = value
180
- return result
181
-
182
- def _parse_command_line_args(self, server_name_or_config: str) -> tuple[str, dict]:
183
- """Parse command-line style arguments into name and config"""
184
- name = ""
185
- config = {}
186
- args = server_name_or_config.strip().split()
187
- i = 0
188
- while i < len(args):
189
- if args[i] == "--name" and i + 1 < len(args):
190
- name = args[i + 1]
191
- i += 2
192
- elif args[i] == "--command" and i + 1 < len(args):
193
- config["command"] = args[i + 1]
194
- i += 2
195
- elif args[i] == "--args":
196
- config["args"] = []
197
- i += 1
198
- while i < len(args) and not args[i].startswith("--"):
199
- config["args"].append(args[i])
200
- i += 1
201
- elif args[i] == "--env":
202
- config["env"] = {}
203
- i += 1
204
- while i < len(args) and not args[i].startswith("--"):
205
- if "=" in args[i]:
206
- key, value = args[i].split("=", 1)
207
- config["env"][key] = value
208
- i += 1
209
- else:
210
- i += 1
211
-
212
- template_config = {}
213
-
214
- if name in MCP_BUILD_IN_SERVERS:
215
- template_config = MCP_BUILD_IN_SERVERS[name]
216
- else:
217
- # 查找外部server
218
- external_servers = get_mcp_external_servers()
219
- for s in external_servers:
220
- if s.name == name:
221
- if s.runtime == "python":
222
- self._install_python_package(name)
223
- template_config = {
224
- "command": "python",
225
- "args": [
226
- "-m", name.replace("-", "_")
227
- ],
228
- }
229
- elif s.runtime == "node":
230
- self._install_node_package(name)
231
- template_config = {
232
- "command": "npx",
233
- "args": [
234
- "-y",
235
- "-g",
236
- name
237
- ]
238
- }
239
- break
240
-
241
- # 深度合并两个配置,以用户配置为主
242
- config = self._deep_merge_dicts(template_config, config)
243
-
244
- if not config.get("args") and (name.startswith("@") or config.get("command") in ["npx", "npm"]):
245
- config["args"] = ["-y", "-g", name]
246
-
247
- ## 如果有模板,则无需再次安装,处理模板的时候会自动安装
248
- if not template_config:
249
- # Install package if needed
250
- if name.startswith("@") or config.get("command") in ["npx", "npm"]:
251
- self._install_node_package(name)
252
- else:
253
- self._install_python_package(name)
254
-
255
- return name, config
256
-
257
- def _parse_json_config(self, server_name_or_config: str) -> tuple[str, dict]:
258
- """Parse JSON configuration into name and config"""
259
- raw_config = json.loads(server_name_or_config)
260
- # 用户给了一个完整的配置
261
- if "mcpServers" in raw_config:
262
- raw_config = raw_config["mcpServers"]
263
-
264
- # 取第一个server 配置
265
- config = list(raw_config.values())[0]
266
- name = list(raw_config.keys())[0]
267
- if name.startswith("@") or config["command"] in ["npx", "npm"]:
268
- for item in config["args"]:
269
- if name in item:
270
- self._install_node_package(item)
271
- else:
272
- self._install_python_package(name)
273
-
274
- return name, config
275
-
276
-
277
- async def _install_server(self, request: McpInstallRequest, hub: McpHub) -> McpResponse:
278
- """Install an MCP server with module dependency check"""
279
- name = ""
280
- config = {}
281
- try:
282
- server_name_or_config = request.server_name_or_config
283
-
284
- # Try different parsing methods
285
- if server_name_or_config.strip().startswith("--"):
286
- # Command-line style arguments
287
- name, config = self._parse_command_line_args(server_name_or_config)
288
- else:
289
- try:
290
- # Try parsing as JSON
291
- name, config = self._parse_json_config(server_name_or_config)
292
- except json.JSONDecodeError:
293
- logger.error(f"Failed to parse JSON config: {server_name_or_config}")
294
- pass
295
-
296
- if not name:
297
- raise ValueError(
298
- "MCP server name is not available in MCP_BUILD_IN_SERVERS or external servers")
299
-
300
- logger.info(f"Installing MCP server: {name} with config: {config}")
301
- if not config:
302
- raise ValueError(f"MCP server {name} config is not available")
303
-
304
- is_success = await hub.add_server_config(name, config)
305
- if is_success:
306
- return McpResponse(result=get_message_with_format("mcp_install_success", result=request.server_name_or_config))
307
- else:
308
- return McpResponse(result="", error=get_message_with_format("mcp_install_error", error="Failed to establish connection"))
309
- except Exception as e:
310
- return McpResponse(result="", error=get_message_with_format("mcp_install_error", error=str(e)))
311
-
312
53
  async def _process_request(self):
313
- hub = McpHub()
54
+ hub = McpHub()
55
+
56
+ ## 可能会阻塞,当mcp settings.json 里有异常内容时
314
57
  await hub.initialize()
315
58
 
316
59
  while self._running:
317
- try:
60
+ try:
318
61
  request = await self._request_queue.get()
319
62
  if request is None:
320
63
  break
321
64
 
322
65
  if isinstance(request, McpInstallRequest):
323
- response = await self._install_server(request, hub)
66
+ response = await self._installer.install_server(request, hub)
324
67
  await self._response_queue.put(response)
325
68
 
326
69
  elif isinstance(request, McpRemoveRequest):
327
70
  try:
328
71
  await hub.remove_server_config(request.server_name)
329
72
  await self._response_queue.put(McpResponse(
330
- result=get_message_with_format("mcp_remove_success", result=request.server_name)))
73
+ result=get_message_with_format("mcp_remove_success", result=request.server_name),
74
+ raw_result=RemoveResult(
75
+ success=True,
76
+ server_name=request.server_name
77
+ )
78
+ ))
331
79
  except Exception as e:
332
80
  await self._response_queue.put(McpResponse(
333
- result="", error=get_message_with_format("mcp_remove_error", error=str(e))))
81
+ result="",
82
+ error=get_message_with_format("mcp_remove_error", error=str(e)),
83
+ raw_result=RemoveResult(
84
+ success=False,
85
+ server_name=request.server_name,
86
+ error=str(e)
87
+ )
88
+ ))
334
89
 
335
90
  elif isinstance(request, McpListRequest):
336
91
  try:
337
- # Get built-in servers
338
- builtin_servers = [
339
- f"- Built-in: {name}" for name in MCP_BUILD_IN_SERVERS.keys()]
92
+ # Get built-in servers
93
+ builtin_servers = []
94
+ for name, config in MCP_BUILD_IN_SERVERS.items():
95
+ marketplace_item = MarketplaceMCPServerItem(
96
+ name=name,
97
+ description=f"Built-in: {name}",
98
+ mcp_type="command",
99
+ command=config.get("command", ""),
100
+ args=config.get("args", []),
101
+ env=config.get("env", {})
102
+ )
103
+ builtin_servers.append(marketplace_item)
340
104
 
341
105
  # Get external servers
342
- external_servers = get_mcp_external_servers()
343
- external_list = [
344
- f"- External: {s.name} ({s.description})" for s in external_servers]
345
-
346
- # Combine results
347
- all_servers = builtin_servers + external_list
348
- result = "\n".join(all_servers)
349
-
350
- await self._response_queue.put(McpResponse(result=result))
106
+ external_servers = self._installer.get_mcp_external_servers()
107
+ external_items = []
108
+ for server in external_servers:
109
+ marketplace_item = MarketplaceMCPServerItem(
110
+ name=server.name,
111
+ description=server.description,
112
+ mcp_type="command"
113
+ )
114
+ external_items.append(marketplace_item)
115
+
116
+ # Get marketplace items
117
+ marketplace_items = hub.get_marketplace_items()
118
+
119
+ # Combine results for display
120
+ result_sections = []
121
+
122
+ if builtin_servers:
123
+ builtin_title = get_message_with_format("mcp_list_builtin_title")
124
+ builtin_list = [f"- {item.name}" for item in builtin_servers]
125
+ result_sections.append(builtin_title)
126
+ result_sections.append("\n".join(builtin_list))
127
+
128
+ if external_items:
129
+ external_title = get_message_with_format("mcp_list_external_title")
130
+ external_list = [f"- {item.name} ({item.description})" for item in external_items]
131
+ result_sections.append(external_title)
132
+ result_sections.append("\n".join(external_list))
133
+
134
+ if marketplace_items:
135
+ marketplace_title = get_message_with_format("mcp_list_marketplace_title")
136
+ marketplace_list = [f"- {item.name} ({item.description})" for item in marketplace_items]
137
+ result_sections.append(marketplace_title)
138
+ result_sections.append("\n".join(marketplace_list))
139
+
140
+ result = "\n\n".join(result_sections)
141
+
142
+ # Create raw result with MarketplaceMCPServerItem objects
143
+ raw_result = ListResult(
144
+ builtin_servers=builtin_servers,
145
+ external_servers=external_items,
146
+ marketplace_items=marketplace_items
147
+ )
148
+
149
+ await self._response_queue.put(McpResponse(result=result, raw_result=raw_result))
351
150
  except Exception as e:
352
151
  await self._response_queue.put(McpResponse(
353
- result="", error=get_message_with_format("mcp_list_builtin_error", error=str(e))))
152
+ result="",
153
+ error=get_message_with_format("mcp_list_builtin_error", error=str(e)),
154
+ raw_result=ListResult(error=str(e))
155
+ ))
354
156
 
355
157
  elif isinstance(request, McpServerInfoRequest):
356
158
  try:
357
159
  llm = get_single_llm(request.model, product_mode=request.product_mode)
358
160
  mcp_executor = McpExecutor(hub, llm)
359
161
  result = mcp_executor.get_connected_servers_info()
360
- await self._response_queue.put(McpResponse(result=result))
162
+ await self._response_queue.put(McpResponse(result=result, raw_result=StringResult(result=result)))
361
163
  except Exception as e:
362
164
  import traceback
363
165
  traceback.print_exc()
364
166
  await self._response_queue.put(McpResponse(
365
- result="", error=get_message_with_format("mcp_server_info_error", error=str(e))))
167
+ result="",
168
+ error=get_message_with_format("mcp_server_info_error", error=str(e)),
169
+ raw_result=ErrorResult(error=str(e))
170
+ ))
366
171
 
367
172
  elif isinstance(request, McpListRunningRequest):
368
173
  try:
174
+ servers = hub.get_servers()
369
175
  running_servers = "\n".join(
370
- [f"- {server.name}" for server in hub.get_servers()])
176
+ [f"- {server.name}" for server in servers])
371
177
  result = running_servers if running_servers else ""
372
- await self._response_queue.put(McpResponse(result=result))
178
+ await self._response_queue.put(McpResponse(
179
+ result=result,
180
+ raw_result=ListRunningResult(
181
+ servers=[ServerInfo(name=server.name) for server in servers]
182
+ )
183
+ ))
373
184
  except Exception as e:
374
185
  await self._response_queue.put(McpResponse(
375
- result="", error=get_message_with_format("mcp_list_running_error", error=str(e))))
186
+ result="",
187
+ error=get_message_with_format("mcp_list_running_error", error=str(e)),
188
+ raw_result=ListRunningResult(error=str(e))
189
+ ))
376
190
 
377
191
  elif isinstance(request, McpRefreshRequest):
378
192
  try:
@@ -381,35 +195,156 @@ class McpServer:
381
195
  else:
382
196
  await hub.initialize()
383
197
  await self._response_queue.put(McpResponse(
384
- result=get_message_with_format("mcp_refresh_success")))
198
+ result=get_message_with_format("mcp_refresh_success"),
199
+ raw_result=RefreshResult(
200
+ success=True,
201
+ name=request.name
202
+ )
203
+ ))
204
+ except Exception as e:
205
+ await self._response_queue.put(McpResponse(
206
+ result="",
207
+ error=get_message_with_format("mcp_refresh_error", error=str(e)),
208
+ raw_result=RefreshResult(
209
+ success=False,
210
+ name=request.name,
211
+ error=str(e)
212
+ )
213
+ ))
214
+
215
+ elif isinstance(request, MarketplaceAddRequest):
216
+ try:
217
+ # Create a MarketplaceMCPServerItem from the request
218
+ item = MarketplaceMCPServerItem(
219
+ name=request.name,
220
+ description=request.description,
221
+ mcp_type=request.mcp_type,
222
+ command=request.command,
223
+ args=request.args or [],
224
+ env=request.env or {},
225
+ url=request.url or ""
226
+ )
227
+
228
+ # Add the item to the marketplace
229
+ success = await hub.add_marketplace_item(item)
230
+
231
+ if success:
232
+ await self._response_queue.put(McpResponse(
233
+ result=get_message_with_format("marketplace_add_success", name=request.name),
234
+ raw_result=MarketplaceAddResult(
235
+ success=True,
236
+ name=request.name
237
+ )
238
+ ))
239
+ else:
240
+ await self._response_queue.put(McpResponse(
241
+ result="",
242
+ error=get_message_with_format("marketplace_add_error", name=request.name),
243
+ raw_result=MarketplaceAddResult(
244
+ success=False,
245
+ name=request.name,
246
+ error=f"Failed to add marketplace item: {request.name}"
247
+ )
248
+ ))
385
249
  except Exception as e:
386
250
  await self._response_queue.put(McpResponse(
387
- result="", error=get_message_with_format("mcp_refresh_error", error=str(e))))
251
+ result="",
252
+ error=get_message_with_format("marketplace_add_error", name=request.name, error=str(e)),
253
+ raw_result=MarketplaceAddResult(
254
+ success=False,
255
+ name=request.name,
256
+ error=str(e)
257
+ )
258
+ ))
259
+
260
+ elif isinstance(request, MarketplaceUpdateRequest):
261
+ try:
262
+ # Create a MarketplaceMCPServerItem from the request
263
+ item = MarketplaceMCPServerItem(
264
+ name=request.name,
265
+ description=request.description,
266
+ mcp_type=request.mcp_type,
267
+ command=request.command,
268
+ args=request.args or [],
269
+ env=request.env or {},
270
+ url=request.url or ""
271
+ )
272
+
273
+ # Update the item in the marketplace
274
+ success = await hub.update_marketplace_item(request.name, item)
275
+
276
+ if success:
277
+ await self._response_queue.put(McpResponse(
278
+ result=get_message_with_format("marketplace_update_success", name=request.name),
279
+ raw_result=MarketplaceUpdateResult(
280
+ success=True,
281
+ name=request.name
282
+ )
283
+ ))
284
+ else:
285
+ await self._response_queue.put(McpResponse(
286
+ result="",
287
+ error=get_message_with_format("marketplace_update_error", name=request.name),
288
+ raw_result=MarketplaceUpdateResult(
289
+ success=False,
290
+ name=request.name,
291
+ error=f"Failed to update marketplace item: {request.name}"
292
+ )
293
+ ))
294
+ except Exception as e:
295
+ await self._response_queue.put(McpResponse(
296
+ result="",
297
+ error=get_message_with_format("marketplace_update_error", name=request.name, error=str(e)),
298
+ raw_result=MarketplaceUpdateResult(
299
+ success=False,
300
+ name=request.name,
301
+ error=str(e)
302
+ )
303
+ ))
388
304
 
389
305
  else:
390
306
  if not request.query.strip():
391
307
  await self._response_queue.put(McpResponse(
392
- result="", error=get_message_with_format("mcp_query_empty")))
308
+ result="",
309
+ error=get_message_with_format("mcp_query_empty"),
310
+ raw_result=QueryResult(
311
+ success=False,
312
+ error="Empty query"
313
+ )
314
+ ))
393
315
  continue
394
-
316
+
395
317
  llm = get_single_llm(request.model, product_mode=request.product_mode)
396
318
  mcp_executor = McpExecutor(hub, llm)
397
319
  conversations = [
398
320
  {"role": "user", "content": request.query}]
399
321
  _, results = await mcp_executor.run(conversations)
400
-
322
+
401
323
  if not results:
402
324
  await self._response_queue.put(McpResponse(
403
- result=get_message_with_format("mcp_error_title"),
404
- error="No results"))
325
+ result=get_message_with_format("mcp_error_title"),
326
+ error="No results",
327
+ raw_result=QueryResult(
328
+ success=False,
329
+ error="No results"
330
+ )
331
+ ))
405
332
  else:
406
333
  results_str = "\n\n".join(
407
334
  mcp_executor.format_mcp_result(result) for result in results)
408
335
  await self._response_queue.put(McpResponse(
409
- result=get_message_with_format("mcp_response_title") + "\n" + results_str))
336
+ result=get_message_with_format("mcp_response_title") + "\n" + results_str,
337
+ raw_result=QueryResult(
338
+ success=True,
339
+ results=results
340
+ )
341
+ ))
410
342
  except Exception as e:
411
343
  await self._response_queue.put(McpResponse(
412
- result="", error=get_message_with_format("mcp_error_title") + ": " + str(e)))
344
+ result="",
345
+ error=get_message_with_format("mcp_error_title") + ": " + str(e),
346
+ raw_result=ErrorResult(error=str(e))
347
+ ))
413
348
 
414
349
  def send_request(self, request: McpRequest) -> McpResponse:
415
350
  async def _send():
@@ -430,3 +365,5 @@ def get_mcp_server():
430
365
  _mcp_server = McpServer()
431
366
  _mcp_server.start()
432
367
  return _mcp_server
368
+
369
+