diff --git a/deploy/k8m-ms.yaml b/deploy/k8m-ms.yaml index 37909e069..f6b73f784 100644 --- a/deploy/k8m-ms.yaml +++ b/deploy/k8m-ms.yaml @@ -153,19 +153,19 @@ spec: spec: containers: - name: k8m - # image: docker.io/weibh/k8m:v0.26.3 - # image: ghcr.io/weibaohui/k8m:v0.26.3 - image: registry.cn-hangzhou.aliyuncs.com/minik8m/k8m:v0.26.3 + # image: docker.io/weibh/k8m:v0.26.6 + # image: ghcr.io/weibaohui/k8m:v0.26.6 + image: registry.cn-hangzhou.aliyuncs.com/minik8m/k8m:v0.26.6 env: - - name: POD_NAME #启用主备选举插件必须填,否则不会切换 + - name: POD_NAME #启用主备选举插件必须填,否则不会切换 valueFrom: fieldRef: fieldPath: metadata.name - - name: POD_NAMESPACE #启用主备选举插件必须填,否则不会切换 + - name: POD_NAMESPACE #启用主备选举插件必须填,否则不会切换 valueFrom: fieldRef: fieldPath: metadata.namespace - - name: POD_IP #启用主备选举插件必须填,否则不会切换 + - name: POD_IP #启用主备选举插件必须填,否则不会切换 valueFrom: fieldRef: fieldPath: status.podIP diff --git a/deploy/k8m.yaml b/deploy/k8m.yaml index dd953bcf5..20804175a 100644 --- a/deploy/k8m.yaml +++ b/deploy/k8m.yaml @@ -153,19 +153,19 @@ spec: spec: containers: - name: k8m - # image: docker.io/weibh/k8m:v0.26.3 - # image: ghcr.io/weibaohui/k8m:v0.26.3 - image: registry.cn-hangzhou.aliyuncs.com/minik8m/k8m:v0.26.3 + # image: docker.io/weibh/k8m:v0.26.6 + # image: ghcr.io/weibaohui/k8m:v0.26.6 + image: registry.cn-hangzhou.aliyuncs.com/minik8m/k8m:v0.26.6 env: - - name: POD_NAME #启用主备选举插件必须填,否则不会切换,单实例运行可以加不影响。 + - name: POD_NAME #启用主备选举插件必须填,否则不会切换,单实例运行可以加不影响。 valueFrom: fieldRef: fieldPath: metadata.name - - name: POD_NAMESPACE #启用主备选举插件必须填,否则不会切换,单实例运行可以加不影响。 + - name: POD_NAMESPACE #启用主备选举插件必须填,否则不会切换,单实例运行可以加不影响。 valueFrom: fieldRef: fieldPath: metadata.namespace - - name: POD_IP #启用主备选举插件必须填,否则不会切换,单实例运行可以加不影响。 + - name: POD_IP #启用主备选举插件必须填,否则不会切换,单实例运行可以加不影响。 valueFrom: fieldRef: fieldPath: status.podIP diff --git a/images/readme.png b/images/readme.png new file mode 100644 index 000000000..abae308a5 Binary files /dev/null and b/images/readme.png differ diff --git a/pkg/plugins/manager_api.go b/pkg/plugins/manager_api.go index 1e375c2fb..845df84e0 100644 --- a/pkg/plugins/manager_api.go +++ b/pkg/plugins/manager_api.go @@ -283,22 +283,82 @@ func (m *Manager) InstallPlugin(c *response.Context) { amis.WriteJsonOKMsg(c, "已安装") } +// ensurePluginEnabledAndRunning 确保插件已安装、已启用且已启动 +// 该方法用于多个管理接口复用:若未安装则先安装;若未启用则先启用;若未启动则启动。 +func (m *Manager) ensurePluginEnabledAndRunning(name string, params *dao.Params) error { + st, ok := m.StatusOf(name) + if !ok || st == StatusUninstalled { + klog.V(6).Infof("插件未安装,先进行安装: %s", name) + if err := m.Install(name); err != nil { + return err + } + if err := m.PersistStatus(name, StatusInstalled, params); err != nil { + return err + } + st = StatusInstalled + } + + if st == StatusInstalled || st == StatusDisabled { + klog.V(6).Infof("插件未启用,先进行启用: %s", name) + if err := m.Enable(name); err != nil { + return err + } + if err := m.PersistStatus(name, StatusEnabled, params); err != nil { + return err + } + st = StatusEnabled + } + + if st == StatusEnabled || st == StatusStopped { + klog.V(6).Infof("插件未启动,进行启动: %s", name) + if err := m.StartPlugin(name); err != nil { + return err + } + if err := m.PersistStatus(name, StatusRunning, params); err != nil { + return err + } + } + + return nil +} + +// ensurePluginDisabled 确保插件处于禁用状态 +// 该方法用于多个管理接口复用:若插件正在运行则先停止,再执行禁用。 +func (m *Manager) ensurePluginDisabled(name string, params *dao.Params) error { + st, _ := m.StatusOf(name) + if st == StatusRunning { + klog.V(6).Infof("插件正在运行,先停止: %s", name) + if err := m.StopPlugin(name); err != nil { + return err + } + if err := m.PersistStatus(name, StatusStopped, params); err != nil { + return err + } + } + + if err := m.Disable(name); err != nil { + return err + } + if err := m.PersistStatus(name, StatusDisabled, params); err != nil { + return err + } + + return nil +} + // EnablePlugin 启用指定名称的插件 // 路径参数为插件名,启用失败时返回错误 func (m *Manager) EnablePlugin(c *response.Context) { name := c.Param("name") klog.V(6).Infof("启用插件配置请求: %s", name) - if err := m.Enable(name); err != nil { - amis.WriteJsonError(c, err) - return - } + params := dao.BuildParams(c) - if err := m.PersistStatus(name, StatusEnabled, params); err != nil { + if err := m.ensurePluginEnabledAndRunning(name, params); err != nil { amis.WriteJsonError(c, err) return } - amis.WriteJsonOKMsg(c, "已启用") + amis.WriteJsonOKMsg(c, "已启用并启动") } // StartPluginAPI 启动指定名称的插件 @@ -378,12 +438,9 @@ func (m *Manager) UninstallPluginKeepData(c *response.Context) { func (m *Manager) DisablePlugin(c *response.Context) { name := c.Param("name") klog.V(6).Infof("禁用插件配置请求: %s", name) - if err := m.Disable(name); err != nil { - amis.WriteJsonError(c, err) - return - } + params := dao.BuildParams(c) - if err := m.PersistStatus(name, StatusDisabled, params); err != nil { + if err := m.ensurePluginDisabled(name, params); err != nil { amis.WriteJsonError(c, err) return } @@ -623,22 +680,10 @@ func (m *Manager) TogglePluginEnabled(c *response.Context) { return } - m.mu.RLock() - currentStatus := m.status[name] - m.mu.RUnlock() + params := dao.BuildParams(c) if enabled == "true" || enabled == "1" || enabled == "yes" { - // 启用插件:已安装或已禁用状态可以启用 - if currentStatus != StatusInstalled && currentStatus != StatusDisabled { - amis.WriteJsonError(c, fmt.Errorf("插件当前状态不允许启用: %s", statusToCN(currentStatus))) - return - } - if err := m.Enable(name); err != nil { - amis.WriteJsonError(c, err) - return - } - params := dao.BuildParams(c) - if err := m.PersistStatus(name, StatusEnabled, params); err != nil { + if err := m.ensurePluginEnabledAndRunning(name, params); err != nil { amis.WriteJsonError(c, err) return } @@ -647,26 +692,7 @@ func (m *Manager) TogglePluginEnabled(c *response.Context) { return } - // 禁用插件:如果正在运行,先停止再禁用 - if currentStatus == StatusRunning { - // 先停止插件 - if err := m.StopPlugin(name); err != nil { - amis.WriteJsonError(c, fmt.Errorf("停止插件失败: %w", err)) - return - } - klog.V(6).Infof("插件已停止: %s", name) - } - // 已停止/已启用/运行中 状态可以禁用 - if currentStatus != StatusStopped && currentStatus != StatusRunning && currentStatus != StatusEnabled { - amis.WriteJsonError(c, fmt.Errorf("插件当前状态不允许禁用: %s", statusToCN(currentStatus))) - return - } - if err := m.Disable(name); err != nil { - amis.WriteJsonError(c, err) - return - } - params := dao.BuildParams(c) - if err := m.PersistStatus(name, StatusDisabled, params); err != nil { + if err := m.ensurePluginDisabled(name, params); err != nil { amis.WriteJsonError(c, err) return } diff --git a/pkg/plugins/modules/inspection/frontend/schedule.json b/pkg/plugins/modules/inspection/frontend/schedule.json index 1022a2095..f86d19196 100644 --- a/pkg/plugins/modules/inspection/frontend/schedule.json +++ b/pkg/plugins/modules/inspection/frontend/schedule.json @@ -60,7 +60,7 @@ "name": "webhooks", "label": "Webhook", "multiple": true, - "source": "/admin/plugins/plugins/webhook/option_list", + "source": "/admin/plugins/webhook/option_list", "labelField": "label", "valueField": "value", "placeholder": "请选择目标Webhook" diff --git a/pkg/plugins/modules/k8m_mcp_server/lifecycle.go b/pkg/plugins/modules/k8m_mcp_server/lifecycle.go index b07354ff9..796a8948e 100644 --- a/pkg/plugins/modules/k8m_mcp_server/lifecycle.go +++ b/pkg/plugins/modules/k8m_mcp_server/lifecycle.go @@ -2,6 +2,7 @@ package k8m_mcp_server import ( "github.com/weibaohui/k8m/pkg/plugins" + "github.com/weibaohui/k8m/pkg/plugins/modules/k8m_mcp_server/models" "k8s.io/klog/v2" ) @@ -9,7 +10,11 @@ type K8mMcpServerLifecycle struct{} func (k *K8mMcpServerLifecycle) Install(ctx plugins.InstallContext) error { klog.V(6).Infof("开始安装K8M MCP Server插件") - klog.V(6).Infof("安装K8M MCP Server插件成功") + if err := models.InitDB(); err != nil { + klog.V(6).Infof("安装 K8M MCP Server 插件失败: %v", err) + return err + } + klog.V(6).Infof("安装 K8M MCP Server 插件成功") return nil } @@ -30,6 +35,12 @@ func (k *K8mMcpServerLifecycle) Disable(ctx plugins.BaseContext) error { func (k *K8mMcpServerLifecycle) Uninstall(ctx plugins.UninstallContext) error { klog.V(6).Infof("开始卸载K8M MCP Server插件") + if !ctx.KeepData() { + if err := models.DropDB(); err != nil { + klog.V(6).Infof("卸载 K8M MCP Server 插件失败: %v", err) + return err + } + } klog.V(6).Infof("卸载K8M MCP Server插件成功") return nil } diff --git a/pkg/plugins/modules/k8m_mcp_server/models/db.go b/pkg/plugins/modules/k8m_mcp_server/models/db.go new file mode 100644 index 000000000..6c1296799 --- /dev/null +++ b/pkg/plugins/modules/k8m_mcp_server/models/db.go @@ -0,0 +1,104 @@ +package models + +import ( + "errors" + "fmt" + + "github.com/weibaohui/k8m/internal/dao" + "github.com/weibaohui/k8m/pkg/flag" + "github.com/weibaohui/k8m/pkg/plugins" + "github.com/weibaohui/k8m/pkg/plugins/modules" + rm "github.com/weibaohui/k8m/pkg/plugins/modules/mcp_runtime/models" + "github.com/weibaohui/k8m/pkg/plugins/modules/mcp_runtime/service" + "gorm.io/gorm" + "k8s.io/klog/v2" +) + +const innerMCPServerName = "k8m" + +// InitDB 初始化本插件安装时需要写入的数据库数据。 +func InitDB() error { + if plugins.ManagerInstance().IsRunning(modules.PluginNameMCPRuntime) { + if err := addInnerMCPServer(); err != nil { + klog.V(6).Infof("初始化内置 MCP Server 配置失败: %v", err) + return err + } + } + return nil +} + +// addInnerMCPServer 检查并初始化名为 "k8m" 的内部 MCP 服务器配置,不存在则创建,已存在则更新其 URL。 +func addInnerMCPServer() error { + // 检查是否存在名为k8m的记录 + var count int64 + if err := dao.DB().Model(&rm.MCPServerConfig{}).Where("name = ?", innerMCPServerName).Count(&count).Error; err != nil { + klog.Errorf("查询MCP服务器配置失败: %v", err) + return err + } + cfg := flag.Init() + // 如果不存在,添加默认的内部MCP服务器配置 + if count == 0 { + config := &rm.MCPServerConfig{ + Name: innerMCPServerName, + URL: fmt.Sprintf("http://localhost:%d/mcp/k8m/sse", cfg.Port), + Enabled: false, + } + if err := dao.DB().Create(config).Error; err != nil { + klog.Errorf("添加内部MCP服务器配置失败: %v", err) + return err + } + klog.V(4).Info("成功添加内部MCP服务器配置") + } else { + klog.V(4).Info("内部MCP服务器配置已存在") + dao.DB().Model(&rm.MCPServerConfig{}).Select("url"). + Where("name =?", innerMCPServerName). + Update("url", fmt.Sprintf("http://localhost:%d/mcp/k8m/sse", cfg.Port)) + } + + return nil +} + +// DropDB 在卸载本插件且不保留数据时,删除内置 MCP Server 配置及相关数据。 +func DropDB() error { + db := dao.DB() + + if !db.Migrator().HasTable(&rm.MCPServerConfig{}) { + klog.V(6).Infof("未发现 MCP Server 配置表,跳过删除内置服务器配置[%s]", innerMCPServerName) + return nil + } + + var server rm.MCPServerConfig + if err := db.Where("name = ?", innerMCPServerName).First(&server).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + klog.V(6).Infof("未找到内置 MCP Server 配置[%s],无需删除", innerMCPServerName) + return nil + } + klog.V(6).Infof("查询内置 MCP Server 配置失败[%s]: %v", innerMCPServerName, err) + return err + } + + if db.Migrator().HasTable(&rm.MCPTool{}) { + if err := db.Where("server_name = ?", innerMCPServerName).Delete(&rm.MCPTool{}).Error; err != nil { + klog.V(6).Infof("删除内置 MCP Server 工具记录失败[%s]: %v", innerMCPServerName, err) + return err + } + } + if db.Migrator().HasTable(&rm.MCPToolLog{}) { + if err := db.Where("server_name = ?", innerMCPServerName).Delete(&rm.MCPToolLog{}).Error; err != nil { + klog.V(6).Infof("删除内置 MCP Server 工具日志失败[%s]: %v", innerMCPServerName, err) + return err + } + } + + if err := db.Where("name = ?", innerMCPServerName).Delete(&rm.MCPServerConfig{}).Error; err != nil { + klog.V(6).Infof("删除内置 MCP Server 配置失败[%s]: %v", innerMCPServerName, err) + return err + } + + if plugins.ManagerInstance().IsRunning(modules.PluginNameMCPRuntime) { + service.McpService().RemoveServer(server) + } + + klog.V(6).Infof("已删除内置 MCP Server 配置及相关数据[%s]", innerMCPServerName) + return nil +} diff --git a/pkg/plugins/modules/mcp_runtime/admin/mcp_server.go b/pkg/plugins/modules/mcp_runtime/admin/mcp_server.go index 1fb0ffe1f..7e2931b85 100644 --- a/pkg/plugins/modules/mcp_runtime/admin/mcp_server.go +++ b/pkg/plugins/modules/mcp_runtime/admin/mcp_server.go @@ -18,7 +18,7 @@ type ServerController struct { // @Summary 获取MCP服务器列表 // @Security BearerAuth // @Success 200 {object} string -// @Router /admin/mcp/list [get] +// @Router /admin/plugins/mcp_runtime/server/list [get] func (m *ServerController) List(c *response.Context) { params := dao.BuildParams(c) var mcpServer models.MCPServerConfig @@ -30,7 +30,7 @@ func (m *ServerController) List(c *response.Context) { // @Security BearerAuth // @Param name path string true "MCP服务器名称" // @Success 200 {object} string -// @Router /admin/mcp/connect/{name} [post] +// @Router /admin/plugins/mcp_runtime/server/connect/{name} [post] func (m *ServerController) Connect(c *response.Context) { name := c.Param("name") ctx := amis.GetContextWithUser(c) @@ -42,7 +42,7 @@ func (m *ServerController) Connect(c *response.Context) { // @Security BearerAuth // @Param request body object true "删除请求体包含IDs数组" // @Success 200 {object} string -// @Router /admin/mcp/delete [post] +// @Router /admin/plugins/mcp_runtime/server/delete [post] func (m *ServerController) Delete(c *response.Context) { var req struct { IDs []int `json:"ids"` @@ -66,7 +66,7 @@ func (m *ServerController) Delete(c *response.Context) { // @Security BearerAuth // @Param request body models.MCPServerConfig true "MCP服务器配置信息" // @Success 200 {object} string -// @Router /admin/mcp/save [post] +// @Router /admin/plugins/mcp_runtime/server/save [post] func (m *ServerController) Save(c *response.Context) { params := dao.BuildParams(c) @@ -95,7 +95,7 @@ func (m *ServerController) Save(c *response.Context) { // @Param id path int true "MCP服务器ID" // @Param status path string true "服务器状态(true/false)" // @Success 200 {object} string -// @Router /admin/mcp/save/id/{id}/status/{status} [post] +// @Router /admin/plugins/mcp_runtime/server/save/id/{id}/status/{status} [post] func (m *ServerController) QuickSave(c *response.Context) { id := c.Param("id") status := c.Param("status") @@ -132,7 +132,7 @@ func (m *ServerController) QuickSave(c *response.Context) { // @Summary 获取MCP服务器日志列表 // @Security BearerAuth // @Success 200 {object} string -// @Router /admin/mcp/log/list [get] +// @Router /admin/plugins/mcp_runtime/server/log/list [get] func (m *ServerController) MCPLogList(c *response.Context) { params := dao.BuildParams(c) var tool models.MCPToolLog diff --git a/pkg/plugins/modules/mcp_runtime/admin/mcp_tool.go b/pkg/plugins/modules/mcp_runtime/admin/mcp_tool.go index 398c2f9f2..59d66033a 100644 --- a/pkg/plugins/modules/mcp_runtime/admin/mcp_tool.go +++ b/pkg/plugins/modules/mcp_runtime/admin/mcp_tool.go @@ -16,7 +16,7 @@ type ToolController struct { // @Security BearerAuth // @Param name path string true "MCP服务器名称" // @Success 200 {object} string -// @Router /admin/mcp/server/{name}/tools/list [get] +// @Router /admin/plugins/mcp_runtime/tool/server/{name}/tools/list [get] func (m *ToolController) List(c *response.Context) { name := c.Param("name") params := dao.BuildParams(c) @@ -37,7 +37,7 @@ func (m *ToolController) List(c *response.Context) { // @Param id path int true "工具ID" // @Param status path string true "状态,例如:true、false" // @Success 200 {object} string -// @Router /admin/mcp/tool/save/id/{id}/status/{status} [post] +// @Router /admin/plugins/mcp_runtime/tool/save/id/{id}/status/{status} [post] func (m *ToolController) QuickSave(c *response.Context) { id := c.Param("id") status := c.Param("status") diff --git a/pkg/plugins/modules/mcp_runtime/models/db.go b/pkg/plugins/modules/mcp_runtime/models/db.go index 9dda6c41a..8b5e2ebbb 100644 --- a/pkg/plugins/modules/mcp_runtime/models/db.go +++ b/pkg/plugins/modules/mcp_runtime/models/db.go @@ -1,12 +1,7 @@ package models import ( - "fmt" - "github.com/weibaohui/k8m/internal/dao" - "github.com/weibaohui/k8m/pkg/flag" - "github.com/weibaohui/k8m/pkg/plugins" - "github.com/weibaohui/k8m/pkg/plugins/modules" "k8s.io/klog/v2" ) @@ -17,9 +12,7 @@ func InitDB() error { &MCPToolLog{}, &McpKey{}, ) - if plugins.ManagerInstance().IsRunning(modules.PluginNameK8mMcpServer) { - addInnerMCPServer() - } + return err } @@ -57,34 +50,3 @@ func DropDB() error { klog.V(6).Infof("已删除 MCP 插件表及数据") return nil } - -// AddInnerMCPServer 检查并初始化名为 "k8m" 的内部 MCP 服务器配置,不存在则创建,已存在则更新其 URL。 -func addInnerMCPServer() error { - // 检查是否存在名为k8m的记录 - var count int64 - if err := dao.DB().Model(&MCPServerConfig{}).Where("name = ?", "k8m").Count(&count).Error; err != nil { - klog.Errorf("查询MCP服务器配置失败: %v", err) - return err - } - cfg := flag.Init() - // 如果不存在,添加默认的内部MCP服务器配置 - if count == 0 { - config := &MCPServerConfig{ - Name: "k8m", - URL: fmt.Sprintf("http://localhost:%d/mcp/k8m/sse", cfg.Port), - Enabled: false, - } - if err := dao.DB().Create(config).Error; err != nil { - klog.Errorf("添加内部MCP服务器配置失败: %v", err) - return err - } - klog.V(4).Info("成功添加内部MCP服务器配置") - } else { - klog.V(4).Info("内部MCP服务器配置已存在") - dao.DB().Model(&MCPServerConfig{}).Select("url"). - Where("name =?", "k8m"). - Update("url", fmt.Sprintf("http://localhost:%d/mcp/k8m/sse", cfg.Port)) - } - - return nil -} diff --git a/pkg/plugins/modules/mcp_runtime/route/admin_api.go b/pkg/plugins/modules/mcp_runtime/route/admin_api.go index 4058227a6..0f629f093 100644 --- a/pkg/plugins/modules/mcp_runtime/route/admin_api.go +++ b/pkg/plugins/modules/mcp_runtime/route/admin_api.go @@ -14,6 +14,7 @@ import ( func RegisterPluginAdminRoutes(arg chi.Router) { prefix := "/plugins/" + modules.PluginNameMCPRuntime serverCtrl := &admin.ServerController{} + arg.Get(prefix+"/server/list", response.Adapter(serverCtrl.List)) arg.Get(prefix+"/server/connect/{name}", response.Adapter(serverCtrl.Connect)) arg.Post(prefix+"/server/delete", response.Adapter(serverCtrl.Delete)) arg.Post(prefix+"/server/save", response.Adapter(serverCtrl.Save)) diff --git a/pkg/plugins/modules/swagger/docs.go b/pkg/plugins/modules/swagger/docs.go index 4378b326a..42f6f3a67 100644 --- a/pkg/plugins/modules/swagger/docs.go +++ b/pkg/plugins/modules/swagger/docs.go @@ -920,222 +920,6 @@ var doc = `{ } } }, - "/admin/mcp/connect/{name}": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "summary": "连接指定MCP服务器", - "parameters": [ - { - "type": "string", - "description": "MCP服务器名称", - "name": "name", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/admin/mcp/delete": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "summary": "删除MCP服务器", - "parameters": [ - { - "description": "删除请求体包含IDs数组", - "name": "request", - "in": "body", - "required": true, - "schema": { - "type": "object" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/admin/mcp/list": { - "get": { - "security": [ - { - "BearerAuth": [] - } - ], - "summary": "获取MCP服务器列表", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/admin/mcp/log/list": { - "get": { - "security": [ - { - "BearerAuth": [] - } - ], - "summary": "获取MCP服务器日志列表", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/admin/mcp/save": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "summary": "创建或更新MCP服务器", - "parameters": [ - { - "description": "MCP服务器配置信息", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/models.MCPServerConfig" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/admin/mcp/save/id/{id}/status/{status}": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "summary": "快速更新MCP服务器状态", - "parameters": [ - { - "type": "integer", - "description": "MCP服务器ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "服务器状态(true/false)", - "name": "status", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/admin/mcp/server/{name}/tools/list": { - "get": { - "security": [ - { - "BearerAuth": [] - } - ], - "summary": "获取指定MCP服务器的工具列表", - "parameters": [ - { - "type": "string", - "description": "MCP服务器名称", - "name": "name", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/admin/mcp/tool/save/id/{id}/status/{status}": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "summary": "快速更新MCP工具状态", - "parameters": [ - { - "type": "integer", - "description": "工具ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "状态,例如:true、false", - "name": "status", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, "/admin/menu/delete/{ids}": { "post": { "security": [ @@ -2024,6 +1808,222 @@ var doc = `{ } } }, + "/admin/plugins/mcp_runtime/server/connect/{name}": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "summary": "连接指定MCP服务器", + "parameters": [ + { + "type": "string", + "description": "MCP服务器名称", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/admin/plugins/mcp_runtime/server/delete": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "summary": "删除MCP服务器", + "parameters": [ + { + "description": "删除请求体包含IDs数组", + "name": "request", + "in": "body", + "required": true, + "schema": { + "type": "object" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/admin/plugins/mcp_runtime/server/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "summary": "获取MCP服务器列表", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/admin/plugins/mcp_runtime/server/log/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "summary": "获取MCP服务器日志列表", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/admin/plugins/mcp_runtime/server/save": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "summary": "创建或更新MCP服务器", + "parameters": [ + { + "description": "MCP服务器配置信息", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.MCPServerConfig" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/admin/plugins/mcp_runtime/server/save/id/{id}/status/{status}": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "summary": "快速更新MCP服务器状态", + "parameters": [ + { + "type": "integer", + "description": "MCP服务器ID", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "服务器状态(true/false)", + "name": "status", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/admin/plugins/mcp_runtime/tool/save/id/{id}/status/{status}": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "summary": "快速更新MCP工具状态", + "parameters": [ + { + "type": "integer", + "description": "工具ID", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "状态,例如:true、false", + "name": "status", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/admin/plugins/mcp_runtime/tool/server/{name}/tools/list": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "summary": "获取指定MCP服务器的工具列表", + "parameters": [ + { + "type": "string", + "description": "MCP服务器名称", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, "/admin/user/2fa/disable/{id}": { "post": { "security": [ @@ -4173,33 +4173,6 @@ var doc = `{ } } }, - "/k8s/cluster/{cluster}/gateway_class/option_list": { - "get": { - "security": [ - { - "BearerAuth": [] - } - ], - "summary": "获取GatewayClass选项列表", - "parameters": [ - { - "type": "string", - "description": "集群名称", - "name": "cluster", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, "/k8s/cluster/{cluster}/ingress_class/option_list": { "get": { "security": [ @@ -11204,28 +11177,35 @@ var doc = `{ "type": "boolean" }, "created_at": { + "description": "创建时间", "type": "string" }, + "floating_window": { + "description": "是否开启浮动窗口", + "type": "boolean" + }, "id": { + "description": "主键ID", "type": "integer" }, "max_history": { - "description": "模型对话上下文历史记录数", + "description": "最大历史记录数", "type": "integer" }, "max_iterations": { - "description": "模型自动对话的最大轮数", + "description": "最大迭代次数", "type": "integer" }, "model_id": { - "description": "选择的模型ID", + "description": "模型ID", "type": "integer" }, "updated_at": { + "description": "更新时间", "type": "string" }, "use_built_in_model": { - "description": "是否使用内置模型,默认开启", + "description": "是否使用内置模型", "type": "boolean" } } @@ -11236,14 +11216,6 @@ var doc = `{ "created_at": { "type": "string" }, - "heartbeat_failure_threshold": { - "description": "心跳失败阈值", - "type": "integer" - }, - "heartbeat_interval_seconds": { - "description": "心跳间隔时间(秒)", - "type": "integer" - }, "id": { "type": "integer" }, @@ -11260,10 +11232,6 @@ var doc = `{ "login_type": { "type": "string" }, - "max_retry_attempts": { - "description": "最大重试次数,默认100次", - "type": "integer" - }, "node_shell_image": { "type": "string" }, @@ -11274,10 +11242,6 @@ var doc = `{ "description": "产品名称", "type": "string" }, - "reconnect_max_interval_seconds": { - "description": "重连最大间隔时间(秒)", - "type": "integer" - }, "resource_cache_timeout": { "description": "资源缓存时间(秒)", "type": "integer" diff --git a/ui/public/pages/plugins/inspection/schedule.json b/ui/public/pages/plugins/inspection/schedule.json index 1022a2095..f86d19196 100644 --- a/ui/public/pages/plugins/inspection/schedule.json +++ b/ui/public/pages/plugins/inspection/schedule.json @@ -60,7 +60,7 @@ "name": "webhooks", "label": "Webhook", "multiple": true, - "source": "/admin/plugins/plugins/webhook/option_list", + "source": "/admin/plugins/webhook/option_list", "labelField": "label", "valueField": "value", "placeholder": "请选择目标Webhook"