Просмотр исходного кода

feat: mcp search support hosted or local type (#270)

* feat: mcp search support hosted or local type

* fix: swag
zijiren 6 месяцев назад
Родитель
Сommit
59fcc8e873

+ 5 - 2
core/controller/mcp/groupmcp.go

@@ -73,7 +73,8 @@ func NewGroupMCPResponses(host string, mcps []model.GroupMCP) []GroupMCPResponse
 //	@Param			group		path		string	true	"Group ID"
 //	@Param			page		query		int		false	"Page number"
 //	@Param			per_page	query		int		false	"Items per page"
-//	@Param			type		query		string	false	"MCP type"
+//	@Param			id			query		string	false	"MCP id"
+//	@Param			type		query		string	false	"MCP type, mcp_proxy_sse, mcp_proxy_streamable, mcp_openapi"
 //	@Param			keyword		query		string	false	"Search keyword"
 //	@Param			status		query		int		false	"MCP status"
 //	@Success		200			{object}	middleware.APIResponse{data=[]GroupMCPResponse}
@@ -86,7 +87,8 @@ func GetGroupMCPs(c *gin.Context) {
 	}
 
 	page, perPage := utils.ParsePageParams(c)
-	mcpType := model.PublicMCPType(c.Query("type"))
+	id := c.Query("id")
+	mcpType := model.GroupMCPType(c.Query("type"))
 	keyword := c.Query("keyword")
 	status, _ := strconv.Atoi(c.Query("status"))
 
@@ -98,6 +100,7 @@ func GetGroupMCPs(c *gin.Context) {
 		groupID,
 		page,
 		perPage,
+		id,
 		mcpType,
 		keyword,
 		model.GroupMCPStatus(status),

+ 13 - 3
core/controller/mcp/publicmcp-group.go

@@ -184,19 +184,29 @@ func NewGroupPublicMCPDetailResponse(
 //	@Param			group		path		string	true	"Group ID"
 //	@Param			page		query		int		false	"Page"
 //	@Param			per_page	query		int		false	"Per Page"
-//	@Param			type		query		string	false	"Type"
+//	@Param			id			query		string	false	"MCP ID"
+//	@Param			type		query		string	false	"hosted or local"
 //	@Param			keyword		query		string	false	"Keyword"
 //	@Success		200			{object}	middleware.APIResponse{data=[]GroupPublicMCPResponse}
 //	@Router			/api/group/{group}/mcp [get]
 func GetGroupPublicMCPs(c *gin.Context) {
 	page, perPage := utils.ParsePageParams(c)
-	mcpType := model.PublicMCPType(c.Query("type"))
+	id := c.Query("id")
+	mcpType := c.Query("type")
+	var mcpTypes []model.PublicMCPType
+	switch mcpType {
+	case "hosted":
+		mcpTypes = getHostedMCPTypes()
+	case "local":
+		mcpTypes = getLocalMCPTypes()
+	}
 	keyword := c.Query("keyword")
 
 	mcps, total, err := model.GetPublicMCPs(
 		page,
 		perPage,
-		mcpType,
+		id,
+		mcpTypes,
 		keyword,
 		model.PublicMCPStatusEnabled,
 	)

+ 27 - 3
core/controller/mcp/publicmcp.go

@@ -79,6 +79,19 @@ func NewPublicMCPResponses(host string, mcps []model.PublicMCP) []PublicMCPRespo
 	return responses
 }
 
+func getHostedMCPTypes() []model.PublicMCPType {
+	return []model.PublicMCPType{
+		model.PublicMCPTypeProxySSE,
+		model.PublicMCPTypeProxyStreamable,
+		model.PublicMCPTypeEmbed,
+		model.PublicMCPTypeOpenAPI,
+	}
+}
+
+func getLocalMCPTypes() []model.PublicMCPType {
+	return []model.PublicMCPType{model.PublicMCPTypeDocs}
+}
+
 // GetPublicMCPs godoc
 //
 //	@Summary		Get MCPs
@@ -88,21 +101,32 @@ func NewPublicMCPResponses(host string, mcps []model.PublicMCP) []PublicMCPRespo
 //	@Security		ApiKeyAuth
 //	@Param			page		query		int		false	"Page number"
 //	@Param			per_page	query		int		false	"Items per page"
-//	@Param			type		query		string	false	"MCP type"
+//	@Param			type		query		string	false	"hosted or local"
+//	@Param			id			query		string	false	"MCP id"
 //	@Param			keyword		query		string	false	"Search keyword"
 //	@Param			status		query		int		false	"MCP status"
 //	@Success		200			{object}	middleware.APIResponse{data=[]PublicMCPResponse}
 //	@Router			/api/mcp/public/ [get]
 func GetPublicMCPs(c *gin.Context) {
 	page, perPage := utils.ParsePageParams(c)
-	mcpType := model.PublicMCPType(c.Query("type"))
+	mcpType := c.Query("type")
+	id := c.Query("id")
 	keyword := c.Query("keyword")
 	status, _ := strconv.Atoi(c.Query("status"))
 
+	var mcpTypes []model.PublicMCPType
+	switch mcpType {
+	case "hosted":
+		mcpTypes = getHostedMCPTypes()
+	case "local":
+		mcpTypes = getLocalMCPTypes()
+	}
+
 	mcps, total, err := model.GetPublicMCPs(
 		page,
 		perPage,
-		mcpType,
+		id,
+		mcpTypes,
 		keyword,
 		model.PublicMCPStatus(status),
 	)

+ 27 - 3
core/docs/docs.go

@@ -1583,7 +1583,13 @@ const docTemplate = `{
                     },
                     {
                         "type": "string",
-                        "description": "Type",
+                        "description": "MCP ID",
+                        "name": "id",
+                        "in": "query"
+                    },
+                    {
+                        "type": "string",
+                        "description": "hosted or local",
                         "name": "type",
                         "in": "query"
                     },
@@ -3364,7 +3370,13 @@ const docTemplate = `{
                     },
                     {
                         "type": "string",
-                        "description": "MCP type",
+                        "description": "MCP id",
+                        "name": "id",
+                        "in": "query"
+                    },
+                    {
+                        "type": "string",
+                        "description": "MCP type, mcp_proxy_sse, mcp_proxy_streamable, mcp_openapi",
                         "name": "type",
                         "in": "query"
                     },
@@ -3700,10 +3712,16 @@ const docTemplate = `{
                     },
                     {
                         "type": "string",
-                        "description": "MCP type",
+                        "description": "hosted or local",
                         "name": "type",
                         "in": "query"
                     },
+                    {
+                        "type": "string",
+                        "description": "MCP id",
+                        "name": "id",
+                        "in": "query"
+                    },
                     {
                         "type": "string",
                         "description": "Search keyword",
@@ -8297,6 +8315,9 @@ const docTemplate = `{
                 "created_at": {
                     "type": "string"
                 },
+                "description": {
+                    "type": "string"
+                },
                 "endpoints": {
                     "$ref": "#/definitions/controller.MCPEndpoint"
                 },
@@ -9850,6 +9871,9 @@ const docTemplate = `{
                 "created_at": {
                     "type": "string"
                 },
+                "description": {
+                    "type": "string"
+                },
                 "group_id": {
                     "type": "string"
                 },

+ 27 - 3
core/docs/swagger.json

@@ -1574,7 +1574,13 @@
                     },
                     {
                         "type": "string",
-                        "description": "Type",
+                        "description": "MCP ID",
+                        "name": "id",
+                        "in": "query"
+                    },
+                    {
+                        "type": "string",
+                        "description": "hosted or local",
                         "name": "type",
                         "in": "query"
                     },
@@ -3355,7 +3361,13 @@
                     },
                     {
                         "type": "string",
-                        "description": "MCP type",
+                        "description": "MCP id",
+                        "name": "id",
+                        "in": "query"
+                    },
+                    {
+                        "type": "string",
+                        "description": "MCP type, mcp_proxy_sse, mcp_proxy_streamable, mcp_openapi",
                         "name": "type",
                         "in": "query"
                     },
@@ -3691,10 +3703,16 @@
                     },
                     {
                         "type": "string",
-                        "description": "MCP type",
+                        "description": "hosted or local",
                         "name": "type",
                         "in": "query"
                     },
+                    {
+                        "type": "string",
+                        "description": "MCP id",
+                        "name": "id",
+                        "in": "query"
+                    },
                     {
                         "type": "string",
                         "description": "Search keyword",
@@ -8288,6 +8306,9 @@
                 "created_at": {
                     "type": "string"
                 },
+                "description": {
+                    "type": "string"
+                },
                 "endpoints": {
                     "$ref": "#/definitions/controller.MCPEndpoint"
                 },
@@ -9841,6 +9862,9 @@
                 "created_at": {
                     "type": "string"
                 },
+                "description": {
+                    "type": "string"
+                },
                 "group_id": {
                     "type": "string"
                 },

+ 19 - 3
core/docs/swagger.yaml

@@ -217,6 +217,8 @@ definitions:
     properties:
       created_at:
         type: string
+      description:
+        type: string
       endpoints:
         $ref: '#/definitions/controller.MCPEndpoint'
       group_id:
@@ -1278,6 +1280,8 @@ definitions:
     properties:
       created_at:
         type: string
+      description:
+        type: string
       group_id:
         type: string
       id:
@@ -3090,7 +3094,11 @@ paths:
         in: query
         name: per_page
         type: integer
-      - description: Type
+      - description: MCP ID
+        in: query
+        name: id
+        type: string
+      - description: hosted or local
         in: query
         name: type
         type: string
@@ -4155,7 +4163,11 @@ paths:
         in: query
         name: per_page
         type: integer
-      - description: MCP type
+      - description: MCP id
+        in: query
+        name: id
+        type: string
+      - description: MCP type, mcp_proxy_sse, mcp_proxy_streamable, mcp_openapi
         in: query
         name: type
         type: string
@@ -4386,10 +4398,14 @@ paths:
         in: query
         name: per_page
         type: integer
-      - description: MCP type
+      - description: hosted or local
         in: query
         name: type
         type: string
+      - description: MCP id
+        in: query
+        name: id
+        type: string
       - description: Search keyword
         in: query
         name: keyword

+ 41 - 7
core/model/groupmcp.go

@@ -2,6 +2,8 @@ package model
 
 import (
 	"errors"
+	"fmt"
+	"strings"
 	"time"
 
 	"github.com/labring/aiproxy/core/common"
@@ -43,6 +45,7 @@ type GroupMCP struct {
 	UpdateAt      time.Time            `gorm:"index,autoUpdateTime"          json:"update_at"`
 	Name          string               `                                     json:"name"`
 	Type          GroupMCPType         `gorm:"index"                         json:"type"`
+	Description   string               `                                     json:"description"`
 	ProxyConfig   *GroupMCPProxyConfig `gorm:"serializer:fastjson;type:text" json:"proxy_config,omitempty"`
 	OpenAPIConfig *MCPOpenAPIConfig    `gorm:"serializer:fastjson;type:text" json:"openapi_config,omitempty"`
 }
@@ -104,6 +107,7 @@ func UpdateGroupMCP(mcp *GroupMCP) (err error) {
 		"name",
 		"proxy_config",
 		"openapi_config",
+		"description",
 	}
 	if mcp.Type != "" {
 		selects = append(selects, "type")
@@ -174,7 +178,8 @@ func GetGroupMCPByID(id, groupID string) (GroupMCP, error) {
 func GetGroupMCPs(
 	groupID string,
 	page, perPage int,
-	mcpType PublicMCPType,
+	id string,
+	mcpType GroupMCPType,
 	keyword string,
 	status GroupMCPStatus,
 ) (mcps []GroupMCP, total int64, err error) {
@@ -184,21 +189,50 @@ func GetGroupMCPs(
 
 	tx := DB.Model(&GroupMCP{}).Where("group_id = ?", groupID)
 
+	if id != "" {
+		tx = tx.Where("id = ?", id)
+	}
+
+	if status != 0 {
+		tx = tx.Where("status = ?", status)
+	}
+
 	if mcpType != "" {
 		tx = tx.Where("type = ?", mcpType)
 	}
 
 	if keyword != "" {
-		keyword = "%" + keyword + "%"
+		var conditions []string
+		var values []any
+
+		if id == "" {
+			if common.UsingPostgreSQL {
+				conditions = append(conditions, "id ILIKE ?")
+				values = append(values, "%"+keyword+"%")
+			} else {
+				conditions = append(conditions, "id LIKE ?")
+				values = append(values, "%"+keyword+"%")
+			}
+		}
+
 		if common.UsingPostgreSQL {
-			tx = tx.Where("name ILIKE ? OR id ILIKE ?", keyword, keyword)
+			conditions = append(conditions, "name ILIKE ?")
+			values = append(values, "%"+keyword+"%")
 		} else {
-			tx = tx.Where("name LIKE ? OR id LIKE ?", keyword, keyword)
+			conditions = append(conditions, "name LIKE ?")
+			values = append(values, "%"+keyword+"%")
+		}
+		if common.UsingPostgreSQL {
+			conditions = append(conditions, "description ILIKE ?")
+			values = append(values, "%"+keyword+"%")
+		} else {
+			conditions = append(conditions, "description LIKE ?")
+			values = append(values, "%"+keyword+"%")
 		}
-	}
 
-	if status != 0 {
-		tx = tx.Where("status = ?", status)
+		if len(conditions) > 0 {
+			tx = tx.Where(fmt.Sprintf("(%s)", strings.Join(conditions, " OR ")), values...)
+		}
 	}
 
 	err = tx.Count(&total).Error

+ 71 - 15
core/model/publicmcp.go

@@ -2,8 +2,10 @@ package model
 
 import (
 	"errors"
+	"fmt"
 	"net/url"
 	"regexp"
+	"strings"
 	"time"
 
 	"github.com/bytedance/sonic"
@@ -320,33 +322,87 @@ func GetPublicMCPByID(id string) (PublicMCP, error) {
 // GetPublicMCPs retrieves MCPs with pagination and filtering
 func GetPublicMCPs(
 	page, perPage int,
-	mcpType PublicMCPType,
+	id string,
+	mcpType []PublicMCPType,
 	keyword string,
 	status PublicMCPStatus,
 ) (mcps []PublicMCP, total int64, err error) {
 	tx := DB.Model(&PublicMCP{})
 
-	if mcpType != "" {
-		tx = tx.Where("type = ?", mcpType)
+	if id != "" {
+		tx = tx.Where("id = ?", id)
+	}
+
+	if status != 0 {
+		tx = tx.Where("status = ?", status)
+	}
+
+	if len(mcpType) > 0 {
+		tx = tx.Where("type IN (?)", mcpType)
 	}
 
 	if keyword != "" {
-		keyword = "%" + keyword + "%"
+		var conditions []string
+		var values []any
+
+		if id == "" {
+			if common.UsingPostgreSQL {
+				conditions = append(conditions, "id ILIKE ?")
+				values = append(values, "%"+keyword+"%")
+			} else {
+				conditions = append(conditions, "id LIKE ?")
+				values = append(values, "%"+keyword+"%")
+			}
+		}
+
 		if common.UsingPostgreSQL {
-			tx = tx.Where(
-				"name ILIKE ? OR author ILIKE ? OR tags ILIKE ? OR id ILIKE ?",
-				keyword,
-				keyword,
-				keyword,
-				keyword,
-			)
+			conditions = append(conditions, "name ILIKE ?")
+			values = append(values, "%"+keyword+"%")
 		} else {
-			tx = tx.Where("name LIKE ? OR author LIKE ? OR tags LIKE ? OR id LIKE ?", keyword, keyword, keyword, keyword)
+			conditions = append(conditions, "name LIKE ?")
+			values = append(values, "%"+keyword+"%")
+		}
+		if common.UsingPostgreSQL {
+			conditions = append(conditions, "name_cn ILIKE ?")
+			values = append(values, "%"+keyword+"%")
+		} else {
+			conditions = append(conditions, "name_cn LIKE ?")
+			values = append(values, "%"+keyword+"%")
 		}
-	}
 
-	if status != 0 {
-		tx = tx.Where("status = ?", status)
+		if common.UsingPostgreSQL {
+			conditions = append(conditions, "description ILIKE ?")
+			values = append(values, "%"+keyword+"%")
+		} else {
+			conditions = append(conditions, "description LIKE ?")
+			values = append(values, "%"+keyword+"%")
+		}
+		if common.UsingPostgreSQL {
+			conditions = append(conditions, "description_cn ILIKE ?")
+			values = append(values, "%"+keyword+"%")
+		} else {
+			conditions = append(conditions, "description_cn LIKE ?")
+			values = append(values, "%"+keyword+"%")
+		}
+
+		if common.UsingPostgreSQL {
+			conditions = append(conditions, "readme ILIKE ?")
+			values = append(values, "%"+keyword+"%")
+		} else {
+			conditions = append(conditions, "readme LIKE ?")
+			values = append(values, "%"+keyword+"%")
+		}
+		if common.UsingPostgreSQL {
+			conditions = append(conditions, "readme_cn ILIKE ?")
+			values = append(values, "%"+keyword+"%")
+		} else {
+			conditions = append(conditions, "readme_cn LIKE ?")
+			values = append(values, "%"+keyword+"%")
+		}
+
+		if len(conditions) > 0 {
+			tx = tx.Where(fmt.Sprintf("(%s)", strings.Join(conditions, " OR ")), values...)
+		}
 	}
 
 	err = tx.Count(&total).Error