From 97cbccc2bacccf2d4b3f59c4d7ccb7c51c637930 Mon Sep 17 00:00:00 2001
From: Soulter <905617992@qq.com>
Date: Thu, 17 Apr 2025 00:41:04 +0800
Subject: [PATCH 1/6] =?UTF-8?q?=E2=9C=A8=20feat:=20mcp=20=E6=9C=8D?=
=?UTF-8?q?=E5=8A=A1=E5=99=A8=E5=B8=82=E5=9C=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
astrbot/dashboard/routes/tools.py | 27 +-
.../src/components/shared/ExtensionCard.vue | 2 +-
dashboard/src/views/ExtensionPage.vue | 2 +-
dashboard/src/views/ToolUsePage.vue | 694 +++++++++++++-----
4 files changed, 540 insertions(+), 185 deletions(-)
diff --git a/astrbot/dashboard/routes/tools.py b/astrbot/dashboard/routes/tools.py
index 9a3c5aa53..af81fe0d2 100644
--- a/astrbot/dashboard/routes/tools.py
+++ b/astrbot/dashboard/routes/tools.py
@@ -1,5 +1,6 @@
import os
import json
+import aiohttp
import traceback
from .route import Route, Response, RouteContext
from quart import request
@@ -20,6 +21,7 @@ class ToolsRoute(Route):
"/tools/mcp/add": ("POST", self.add_mcp_server),
"/tools/mcp/update": ("POST", self.update_mcp_server),
"/tools/mcp/delete": ("POST", self.delete_mcp_server),
+ "/tools/mcp/market": ("GET", self.get_mcp_markets),
}
self.register_routes()
self.tool_mgr = self.core_lifecycle.provider_manager.llm_tools
@@ -107,7 +109,9 @@ class ToolsRoute(Route):
for key, value in server_data.items():
if key not in ["name", "active", "tools"]: # 排除特殊字段
if key == "mcpServers":
- key_0 = list(server_data["mcpServers"].keys())[0] # 不考虑为空的情况
+ key_0 = list(server_data["mcpServers"].keys())[
+ 0
+ ] # 不考虑为空的情况
server_config = server_data["mcpServers"][key_0]
else:
server_config[key] = value
@@ -168,7 +172,9 @@ class ToolsRoute(Route):
for key, value in server_data.items():
if key not in ["name", "active", "tools"]: # 排除特殊字段
if key == "mcpServers":
- key_0 = list(server_data["mcpServers"].keys())[0] # 不考虑为空的情况
+ key_0 = list(server_data["mcpServers"].keys())[
+ 0
+ ] # 不考虑为空的情况
server_config = server_data["mcpServers"][key_0]
else:
server_config[key] = value
@@ -258,3 +264,20 @@ class ToolsRoute(Route):
except Exception as e:
logger.error(traceback.format_exc())
return Response().error(f"删除 MCP 服务器失败: {str(e)}").__dict__
+
+ async def get_mcp_markets(self):
+ BASE_URL = "https://api.soulter.top/astrbot/mcpservers"
+ try:
+ async with aiohttp.ClientSession() as session:
+ async with session.get(f"{BASE_URL}") as response:
+ if response.status == 200:
+ data = await response.json()
+ return Response().ok(data["data"]).__dict__
+ else:
+ return (
+ Response()
+ .error(f"获取市场数据失败: HTTP {response.status}")
+ .__dict__
+ )
+ except Exception as _:
+ logger.error(traceback.format_exc())
diff --git a/dashboard/src/components/shared/ExtensionCard.vue b/dashboard/src/components/shared/ExtensionCard.vue
index e6573260c..73da2f4b5 100644
--- a/dashboard/src/components/shared/ExtensionCard.vue
+++ b/dashboard/src/components/shared/ExtensionCard.vue
@@ -81,7 +81,7 @@ const viewReadme = () => {
{{ extension.author }} /
-
+
{{ extension.name }}
diff --git a/dashboard/src/views/ExtensionPage.vue b/dashboard/src/views/ExtensionPage.vue
index 40441c273..5adb03234 100644
--- a/dashboard/src/views/ExtensionPage.vue
+++ b/dashboard/src/views/ExtensionPage.vue
@@ -402,7 +402,7 @@ onMounted(async () => {
已安装的插件
- 管理您已经安装的所有机器人插件
+ 管理已经安装的所有插件
diff --git a/dashboard/src/views/ToolUsePage.vue b/dashboard/src/views/ToolUsePage.vue
index a3121f0f6..c5499ca8b 100644
--- a/dashboard/src/views/ToolUsePage.vue
+++ b/dashboard/src/views/ToolUsePage.vue
@@ -27,198 +27,315 @@
-
-
-
- mdi-server
- MCP 服务器
-
-
-
- 新增服务器
-
-
+
+
+
+ mdi-server
+ 本地服务器
+
+
+ mdi-store
+ MCP 市场
+
+ 浏览和安装来自社区的 MCP 服务器
+
+
+
-
+
+
+
+
+
+
+ mdi-server
+ MCP 服务器
+
+
+
+ 新增服务器
+
+
-
-
-
- mdi-server-off
- 暂无 MCP 服务器,点击"新增服务器"添加
-
-
+
-
-
-
-
-
- {{ server.name }}
-
-
-
-
- {{ server.active ? '已启用' : '已禁用' }}
-
-
+
+
+
+ mdi-server-off
+ 暂无 MCP 服务器,点击"新增服务器"添加
+
+
+
+
+
+
+
+
+ {{ server.name }}
+
+
+
+
+ {{ server.active ? '已启用' : '已禁用' }}
+
+
+
+
+
+ mdi-file-code
+
+ {{ getServerConfigSummary(server) }}
+
+
+
+
+
+ mdi-tools
+ 可用工具 ({{ server.tools.length }})
+
+
+
+ {{ tool }}
+
+
+
+
+ mdi-alert-circle
+ 无可用工具
+
+
+
+
+
+
+
+
+ 删除
+
+
+ 编辑
+
+
+
+
+
+
+
+
+
+
+
+ mdi-function
+ 函数工具
+ {{ tools.length }}
+
+
+ {{ showTools ? '收起' : '展开' }}
+ {{ showTools ? 'mdi-chevron-up' : 'mdi-chevron-down' }}
+
+
+
+
+
+
+
+
+
mdi-api-off
+
没有可用的函数工具
+
-
-
- mdi-file-code
-
- {{ getServerConfigSummary(server) }}
-
-
-
-
-
- mdi-tools
- 可用工具 ({{ server.tools.length }})
-
-
-
- {{ tool }}
-
-
-
-
- mdi-alert-circle
- 无可用工具
-
-
-
-
-
-
-
-
- 删除
-
-
- 编辑
-
-
-
-
-
-
-
+
+
-
-
-
- mdi-function
- 函数工具
- {{ tools.length }}
-
-
- {{ showTools ? '收起' : '展开' }}
- {{ showTools ? 'mdi-chevron-up' : 'mdi-chevron-down' }}
-
-
+
+
+
+
+
+
+
+ {{ tool.function.name.includes(':') ? 'mdi-server-network' : 'mdi-function-variant' }}
+
+
+ {{ formatToolName(tool.function.name) }}
+
+
+
+
+ {{ tool.function.description }}
+
+
+
+
+
+
+
+
+ mdi-information
+ 功能描述
+
+ {{ tool.function.description }}
+
+
+
+ mdi-code-json
+ 参数列表
+
+
+
+
+
+ | 参数名 |
+ 类型 |
+ 描述 |
+
+
+
+
+ | {{ paramName }} |
+
+
+ {{ param.type }}
+
+ |
+ {{ param.description }} |
+
+
+
+
+
+
mdi-code-brackets
+
此工具没有参数
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
mdi-api-off
-
没有可用的函数工具
-
-
-
+
+
+
+
+ mdi-store
+ MCP 服务器市场
+
+
+ 刷新
+
+
-
-
-
-
-
-
-
- {{ tool.function.name.includes(':') ? 'mdi-server-network' : 'mdi-function-variant' }}
-
-
- {{ formatToolName(tool.function.name) }}
-
-
-
-
- {{ tool.function.description }}
-
-
-
-
-
-
-
-
- mdi-information
- 功能描述
-
- {{ tool.function.description }}
-
-
-
- mdi-code-json
- 参数列表
-
-
-
-
-
- | 参数名 |
- 类型 |
- 描述 |
-
-
-
-
- | {{ paramName }} |
-
-
- {{ param.type }}
-
- |
- {{ param.description }} |
-
-
-
-
-
-
mdi-code-brackets
-
此工具没有参数
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
mdi-store-off
+
暂无可用的 MCP 服务器
+
+
+
+
+
+
+
+
+ {{ server.name_h }}({{ server.name }})
+
+
+
+
+
+
+
+ mdi-tools
+
+ 可用工具 ({{ server.tools ? server.tools.length : 0 }})
+
+
+
+
+
+ {{ tool.name }}
+
+
+
+ mdi-alert-circle
+ 无可用工具信息
+
+
+
+
+
+
+
+
+ 详情
+
+
+ 导入
+
+
+
+
+
+
+
+
+
@@ -324,6 +441,119 @@
+
+
+
+
+ mdi-information-outline
+ 服务器详情
+
+
+ mdi-close
+
+
+
+
+ {{ selectedMarketplaceServer.name }}
+
+
+
+
+
+
+
+ 可用工具
+ {{ selectedMarketplaceServer.tools.length }}
+
+
+
+
+
+
+ mdi-function-variant
+ {{ tool.name }}
+
+
+
+
+ {{ tool.description }}
+
+
+ 参数列表
+
+
+
+ | 参数名 |
+ 类型 |
+ 必填 |
+ 描述 |
+
+
+
+
+ | {{ paramName }} |
+
+
+ {{ param.type }}
+
+ |
+
+
+ mdi-check
+
+ 否
+ |
+ {{ param.description }} |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 关闭
+
+
+ 导入配置
+
+
+
+
+
@@ -345,9 +575,11 @@ export default {
},
data() {
return {
+ activeTab: 'local', // 当前激活的标签页
mcpServers: [],
tools: [],
showMcpServerDialog: false,
+ showServerDetailDialog: false,
showTools: true,
loading: false,
isEditMode: false,
@@ -363,6 +595,13 @@ export default {
save_message_success: "success",
toolSearch: '',
openedPanel: [], // 存储打开的面板索引
+
+ // MCP 市场相关
+ marketplaceServers: [],
+ marketplaceLoading: false,
+ marketplaceSearch: '',
+ selectedMarketplaceServer: null,
+ selectedServerConfigDisplay: '',
}
},
@@ -399,23 +638,26 @@ export default {
return '未设置配置';
}
- }
+ },
},
mounted() {
this.getServers();
this.getTools();
+ this.fetchMarketplaceServers();
+
+ // 定期刷新本地服务器列表
setInterval(() => {
this.getServers();
this.getTools();
- }, 5000); // 每 5 秒刷新一次服务器列表
-
+ }, 5000);
},
methods: {
openurl(url) {
window.open(url, '_blank');
},
+
formatToolName(name) {
if (name.includes(':')) {
// MCP 工具通常命名为 mcp:server:tool
@@ -590,6 +832,82 @@ export default {
this.save_message = message;
this.save_message_success = "error";
this.save_message_snack = true;
+ },
+
+ // MCP 市场相关方法
+
+ // 获取市场服务器列表
+ fetchMarketplaceServers() {
+ this.marketplaceLoading = true;
+ axios.get('/api/tools/mcp/market')
+ .then(response => {
+ this.marketplaceServers = response.data.data.mcpservers || [];
+ this.marketplaceLoading = false;
+ })
+ .catch(error => {
+ this.showError("获取 MCP 市场服务器列表失败: " + error.message);
+ this.marketplaceLoading = false;
+ });
+ },
+
+ // 显示服务器详情
+ showServerDetail(server) {
+ this.selectedMarketplaceServer = server;
+
+ // 格式化服务器配置的显示
+ try {
+ if (server.config) {
+ const configs = JSON.parse(server.config);
+ this.selectedServerConfigDisplay = JSON.stringify(configs[0], null, 2);
+ } else {
+ this.selectedServerConfigDisplay = '// 无可用配置';
+ }
+ } catch (e) {
+ this.selectedServerConfigDisplay = '// 配置解析错误: ' + e.message;
+ }
+
+ this.showServerDetailDialog = true;
+ },
+
+ // 导入服务器配置
+ importServerConfig(server) {
+ try {
+ // 解析服务器配置
+ if (!server.config) {
+ this.showError('此服务器没有可用配置');
+ return;
+ }
+
+ const configs = JSON.parse(server.config);
+ if (!configs || !configs[0] || !configs[0].mcpServers) {
+ this.showError('服务器配置格式不正确');
+ return;
+ }
+
+ // 找到服务器名称和配置
+ const serverName = server.name;
+ const serverConfig = configs[0]
+
+ // 设置表单数据
+ this.currentServer = {
+ name: serverName,
+ active: true,
+ tools: []
+ };
+
+ // 设置配置JSON
+ this.serverConfigJson = JSON.stringify(serverConfig, null, 2);
+
+ // 关闭详情对话框(如果打开的话)
+ this.showServerDetailDialog = false;
+
+ // 打开添加服务器对话框
+ this.isEditMode = false;
+ this.showMcpServerDialog = true;
+
+ } catch (e) {
+ this.showError('导入配置失败: ' + e.message);
+ }
}
}
}
@@ -655,4 +973,18 @@ export default {
height: 300px;
overflow: hidden;
}
+
+.marketplace-card {
+ position: relative;
+ border-radius: 8px;
+ transition: all 0.3s ease;
+}
+
+.text-truncate-2 {
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
\ No newline at end of file
From 33fd6a5016fd7efcce2e8112e2ca83a31a944357 Mon Sep 17 00:00:00 2001
From: Soulter <905617992@qq.com>
Date: Thu, 17 Apr 2025 13:59:10 +0800
Subject: [PATCH 2/6] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=20MCP=20?=
=?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=99=A8=E7=9A=84=E6=97=A5=E5=BF=97=E5=9B=9E?=
=?UTF-8?q?=E6=98=BE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
astrbot/core/log.py | 5 ++-
astrbot/core/provider/func_tool_manager.py | 44 +++++++++++++++-------
astrbot/core/utils/log_pipe.py | 36 ++++++++++++++++++
astrbot/dashboard/routes/tools.py | 9 +++--
dashboard/src/views/ToolUsePage.vue | 39 +++++++++++++++----
5 files changed, 107 insertions(+), 26 deletions(-)
create mode 100644 astrbot/core/utils/log_pipe.py
diff --git a/astrbot/core/log.py b/astrbot/core/log.py
index 6609b8246..9b78eaec6 100644
--- a/astrbot/core/log.py
+++ b/astrbot/core/log.py
@@ -25,6 +25,7 @@ import logging
import colorlog
import asyncio
import os
+import sys
from collections import deque
from asyncio import Queue
from typing import List
@@ -171,7 +172,9 @@ class LogManager:
if logger.hasHandlers():
return logger
# 如果logger没有处理器
- console_handler = logging.StreamHandler() # 创建一个StreamHandler用于控制台输出
+ console_handler = logging.StreamHandler(
+ sys.stdout
+ ) # 创建一个StreamHandler用于控制台输出
console_handler.setLevel(
logging.DEBUG
) # 将日志级别设置为DEBUG(最低级别, 显示所有日志), *如果插件没有设置级别, 默认为DEBUG
diff --git a/astrbot/core/provider/func_tool_manager.py b/astrbot/core/provider/func_tool_manager.py
index 53f5048fa..793d21a12 100644
--- a/astrbot/core/provider/func_tool_manager.py
+++ b/astrbot/core/provider/func_tool_manager.py
@@ -4,12 +4,14 @@ import textwrap
import os
import asyncio
import copy
+import logging
from typing import Dict, List, Awaitable, Literal, Any
from dataclasses import dataclass
from typing import Optional
from contextlib import AsyncExitStack
from astrbot import logger
+from astrbot.core.utils.log_pipe import LogPipe
try:
import mcp
@@ -87,8 +89,9 @@ class MCPClient:
self.name = None
self.active: bool = True
self.tools: List[mcp.Tool] = []
+ self.server_errlogs: List[str] = []
- async def connect_to_server(self, mcp_server_config: dict):
+ async def connect_to_server(self, mcp_server_config: dict, name: str):
"""Connect to an MCP server
Args:
@@ -98,19 +101,30 @@ class MCPClient:
if "mcpServers" in cfg and len(cfg["mcpServers"]) > 0:
key_0 = list(cfg["mcpServers"].keys())[0]
cfg = cfg["mcpServers"][key_0]
- cfg.pop("active", None) # Remove active flag from config
+ cfg.pop("active", None) # Remove active flag from config
server_params = mcp.StdioServerParameters(
**cfg,
)
+ def callback(msg: str):
+ # 处理 MCP 服务的错误日志
+ self.server_errlogs.append(msg)
+
stdio_transport = await self.exit_stack.enter_async_context(
- mcp.stdio_client(server_params)
+ mcp.stdio_client(
+ server_params,
+ errlog=LogPipe(
+ level=logging.ERROR,
+ logger=logger,
+ identifier=f"MCPServer-{name}",
+ callback=callback,
+ ),
+ ),
)
self.stdio, self.write = stdio_transport
self.session = await self.exit_stack.enter_async_context(
mcp.ClientSession(self.stdio, self.write)
)
-
await self.session.initialize()
async def list_tools_and_save(self) -> mcp.ListToolsResult:
@@ -266,7 +280,9 @@ class FuncCall:
self.func_list = [
f
for f in self.func_list
- if not (f.origin == "mcp" and f.mcp_server_name == data["name"])
+ if not (
+ f.origin == "mcp" and f.mcp_server_name == data["name"]
+ )
]
else:
for name in self.mcp_client_dict.keys():
@@ -275,11 +291,7 @@ class FuncCall:
if name in self.mcp_client_event:
self.mcp_client_event[name].set()
self.mcp_client_event.pop(name, None)
- self.func_list = [
- f
- for f in self.func_list
- if f.origin != "mcp"
- ]
+ self.func_list = [f for f in self.func_list if f.origin != "mcp"]
async def _init_mcp_client_task_wrapper(
self, name: str, cfg: dict, event: asyncio.Event
@@ -291,6 +303,9 @@ class FuncCall:
logger.info(f"收到 MCP 客户端 {name} 终止信号")
await self._terminate_mcp_client(name)
except Exception as e:
+ import traceback
+
+ traceback.print_exc()
logger.error(f"初始化 MCP 客户端 {name} 失败: {e}")
async def _init_mcp_client(self, name: str, config: dict) -> None:
@@ -302,10 +317,10 @@ class FuncCall:
mcp_client = MCPClient()
mcp_client.name = name
- await mcp_client.connect_to_server(config)
+ self.mcp_client_dict[name] = mcp_client
+ await mcp_client.connect_to_server(config, name)
tools_res = await mcp_client.list_tools_and_save()
tool_names = [tool.name for tool in tools_res.tools]
- self.mcp_client_dict[name] = mcp_client
# 移除该MCP服务之前的工具(如有)
self.func_list = [
@@ -329,6 +344,9 @@ class FuncCall:
logger.info(f"已连接 MCP 服务 {name}, Tools: {tool_names}")
return True
except Exception as e:
+ import traceback
+
+ logger.error(traceback.format_exc())
logger.error(f"初始化 MCP 客户端 {name} 失败: {e}")
# 发生错误时确保客户端被清理
if name in self.mcp_client_dict:
@@ -352,7 +370,7 @@ class FuncCall:
]
logger.info(f"已关闭 MCP 服务 {name}")
- def get_func_desc_openai_style(self, omit_empty_parameter_field = False) -> list:
+ def get_func_desc_openai_style(self, omit_empty_parameter_field=False) -> list:
"""
获得 OpenAI API 风格的**已经激活**的工具描述
"""
diff --git a/astrbot/core/utils/log_pipe.py b/astrbot/core/utils/log_pipe.py
new file mode 100644
index 000000000..bf5402f17
--- /dev/null
+++ b/astrbot/core/utils/log_pipe.py
@@ -0,0 +1,36 @@
+import threading
+import os
+from logging import Logger
+
+
+class LogPipe(threading.Thread):
+ def __init__(
+ self,
+ level,
+ logger: Logger,
+ identifier=None,
+ callback=None,
+ ):
+ threading.Thread.__init__(self)
+ self.daemon = True
+ self.level = level
+ self.fd_read, self.fd_write = os.pipe()
+ self.identifier = identifier
+ self.logger = logger
+ self.callback = callback
+ self.reader = os.fdopen(self.fd_read)
+ self.start()
+
+ def fileno(self):
+ return self.fd_write
+
+ def run(self):
+ for line in iter(self.reader.readline, ""):
+ if self.callback:
+ self.callback(line.strip())
+ self.logger.log(self.level, f"[{self.identifier}] {line.strip()}")
+
+ self.reader.close()
+
+ def close(self):
+ os.close(self.fd_write)
diff --git a/astrbot/dashboard/routes/tools.py b/astrbot/dashboard/routes/tools.py
index af81fe0d2..9fda62cea 100644
--- a/astrbot/dashboard/routes/tools.py
+++ b/astrbot/dashboard/routes/tools.py
@@ -80,6 +80,7 @@ class ToolsRoute(Route):
) in self.tool_mgr.mcp_client_dict.items():
if name_key == name:
server_info["tools"] = [tool.name for tool in mcp_client.tools]
+ server_info["errlogs"] = mcp_client.server_errlogs
break
else:
server_info["tools"] = []
@@ -107,7 +108,7 @@ class ToolsRoute(Route):
# 复制所有配置字段
for key, value in server_data.items():
- if key not in ["name", "active", "tools"]: # 排除特殊字段
+ if key not in ["name", "active", "tools", "errlogs"]: # 排除特殊字段
if key == "mcpServers":
key_0 = list(server_data["mcpServers"].keys())[
0
@@ -129,7 +130,7 @@ class ToolsRoute(Route):
if self.save_mcp_config(config):
# 动态初始化新MCP客户端
- self.tool_mgr.mcp_service_queue.put_nowait(
+ await self.tool_mgr.mcp_service_queue.put(
{
"type": "init",
"name": name,
@@ -170,7 +171,7 @@ class ToolsRoute(Route):
# 复制所有配置字段
for key, value in server_data.items():
- if key not in ["name", "active", "tools"]: # 排除特殊字段
+ if key not in ["name", "active", "tools", "errlogs"]: # 排除特殊字段
if key == "mcpServers":
key_0 = list(server_data["mcpServers"].keys())[
0
@@ -208,7 +209,7 @@ class ToolsRoute(Route):
)
else:
# 客户端不存在,初始化
- self.tool_mgr.mcp_service_queue.put_nowait(
+ await self.tool_mgr.mcp_service_queue.put(
{
"type": "init",
"name": name,
diff --git a/dashboard/src/views/ToolUsePage.vue b/dashboard/src/views/ToolUsePage.vue
index c5499ca8b..c977613e5 100644
--- a/dashboard/src/views/ToolUsePage.vue
+++ b/dashboard/src/views/ToolUsePage.vue
@@ -55,9 +55,11 @@
mdi-server
MCP 服务器
-
-
+
+ 刷新
+
+
新增服务器
@@ -77,7 +79,21 @@
- {{ server.name }}
+
+
{{ server.name }}
+
+
+
+
+ mdi-alert-circle
+ 异常
+
+
+ {{ server.errlogs }}
+
+
+
+
{
this.mcpServers = response.data.data || [];
- this.loading = false
})
.catch(error => {
this.showError("获取 MCP 服务器列表失败: " + error.message);
- this.loading = false
+ }).finally(() => {
+ setTimeout(() => {
+ this.loading = false;
+ }, 500);
});
},
@@ -775,9 +793,14 @@ export default {
const configCopy = { ...server };
// 移除基本字段,只保留配置相关字段
- delete configCopy.name;
- delete configCopy.active;
- delete configCopy.tools;
+ try {
+ delete configCopy.name;
+ delete configCopy.active;
+ delete configCopy.tools;
+ delete configCopy.errlogs;
+ } catch (e) {
+ console.error("Error removing basic fields: ", e);
+ }
// 设置当前服务器的基本信息
this.currentServer = {
From b9b260f26a2c461197ea45605c323bc9b703825f Mon Sep 17 00:00:00 2001
From: Soulter <905617992@qq.com>
Date: Thu, 17 Apr 2025 14:02:40 +0800
Subject: [PATCH 3/6] =?UTF-8?q?perf:=20=E5=BC=B1=E5=8C=96=E6=98=BE?=
=?UTF-8?q?=E7=A4=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
dashboard/src/views/ToolUsePage.vue | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dashboard/src/views/ToolUsePage.vue b/dashboard/src/views/ToolUsePage.vue
index c977613e5..01de562e0 100644
--- a/dashboard/src/views/ToolUsePage.vue
+++ b/dashboard/src/views/ToolUsePage.vue
@@ -85,8 +85,8 @@
- mdi-alert-circle
- 异常
+ mdi-information
+ 日志
{{ server.errlogs }}
From dc87006fed68375108a33f9b20574b00b8eb0f8f Mon Sep 17 00:00:00 2001
From: Soulter <905617992@qq.com>
Date: Thu, 17 Apr 2025 16:07:13 +0800
Subject: [PATCH 4/6] =?UTF-8?q?feat:=20=E5=88=86=E9=A1=B5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
astrbot/dashboard/routes/tools.py | 8 ++-
dashboard/src/views/ToolUsePage.vue | 79 ++++++++++++++++++++++++++---
2 files changed, 78 insertions(+), 9 deletions(-)
diff --git a/astrbot/dashboard/routes/tools.py b/astrbot/dashboard/routes/tools.py
index 9fda62cea..6dd093546 100644
--- a/astrbot/dashboard/routes/tools.py
+++ b/astrbot/dashboard/routes/tools.py
@@ -267,7 +267,12 @@ class ToolsRoute(Route):
return Response().error(f"删除 MCP 服务器失败: {str(e)}").__dict__
async def get_mcp_markets(self):
- BASE_URL = "https://api.soulter.top/astrbot/mcpservers"
+ page = request.args.get("page", 1, type=int)
+ page_size = request.args.get("page_size", 10, type=int)
+ BASE_URL = "https://api.soulter.top/astrbot/mcpservers?page={}&page_size={}".format(
+ page,
+ page_size,
+ )
try:
async with aiohttp.ClientSession() as session:
async with session.get(f"{BASE_URL}") as response:
@@ -282,3 +287,4 @@ class ToolsRoute(Route):
)
except Exception as _:
logger.error(traceback.format_exc())
+ return Response().error("获取市场数据失败").__dict__
\ No newline at end of file
diff --git a/dashboard/src/views/ToolUsePage.vue b/dashboard/src/views/ToolUsePage.vue
index 01de562e0..54bd337ff 100644
--- a/dashboard/src/views/ToolUsePage.vue
+++ b/dashboard/src/views/ToolUsePage.vue
@@ -277,8 +277,9 @@
class="mx-2"
style="max-width: 300px"
clearable
+ @update:model-value="searchMarketplaceServers"
>
-
+
刷新
@@ -293,25 +294,29 @@
-