groupmcp.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. package model
  2. import (
  3. "errors"
  4. "fmt"
  5. "strings"
  6. "time"
  7. "github.com/labring/aiproxy/core/common"
  8. log "github.com/sirupsen/logrus"
  9. "gorm.io/gorm"
  10. )
  11. type GroupMCPStatus int
  12. const (
  13. GroupMCPStatusEnabled GroupMCPStatus = iota + 1
  14. GroupMCPStatusDisabled
  15. )
  16. const (
  17. ErrGroupMCPNotFound = "group mcp"
  18. )
  19. type GroupMCPType string
  20. const (
  21. GroupMCPTypeProxySSE GroupMCPType = "mcp_proxy_sse"
  22. GroupMCPTypeProxyStreamable GroupMCPType = "mcp_proxy_streamable"
  23. GroupMCPTypeOpenAPI GroupMCPType = "mcp_openapi"
  24. )
  25. type GroupMCPProxyConfig struct {
  26. URL string `json:"url"`
  27. Querys map[string]string `json:"querys"`
  28. Headers map[string]string `json:"headers"`
  29. }
  30. type GroupMCP struct {
  31. ID string `gorm:"primaryKey" json:"id"`
  32. GroupID string `gorm:"primaryKey" json:"group_id"`
  33. Group *Group `gorm:"foreignKey:GroupID" json:"-"`
  34. Status GroupMCPStatus `gorm:"index;default:1" json:"status"`
  35. CreatedAt time.Time `gorm:"index,autoCreateTime" json:"created_at"`
  36. UpdateAt time.Time `gorm:"index,autoUpdateTime" json:"update_at"`
  37. Name string ` json:"name"`
  38. Type GroupMCPType `gorm:"index" json:"type"`
  39. Description string ` json:"description"`
  40. ProxyConfig *GroupMCPProxyConfig `gorm:"serializer:fastjson;type:text" json:"proxy_config,omitempty"`
  41. OpenAPIConfig *MCPOpenAPIConfig `gorm:"serializer:fastjson;type:text" json:"openapi_config,omitempty"`
  42. }
  43. func (g *GroupMCP) BeforeSave(_ *gorm.DB) (err error) {
  44. if g.GroupID == "" {
  45. return errors.New("group id is empty")
  46. }
  47. if err := validateMCPID(g.ID); err != nil {
  48. return err
  49. }
  50. if g.UpdateAt.IsZero() {
  51. g.UpdateAt = time.Now()
  52. }
  53. if g.Status == 0 {
  54. g.Status = GroupMCPStatusEnabled
  55. }
  56. if g.OpenAPIConfig != nil {
  57. config := g.OpenAPIConfig
  58. if config.OpenAPISpec != "" {
  59. return validateHTTPURL(config.OpenAPISpec)
  60. }
  61. if config.OpenAPIContent != "" {
  62. return nil
  63. }
  64. return errors.New("openapi spec and content is empty")
  65. }
  66. if g.ProxyConfig != nil {
  67. config := g.ProxyConfig
  68. return validateHTTPURL(config.URL)
  69. }
  70. return err
  71. }
  72. // CreateGroupMCP creates a new GroupMCP
  73. func CreateGroupMCP(mcp *GroupMCP) error {
  74. err := DB.Create(mcp).Error
  75. if err != nil && errors.Is(err, gorm.ErrDuplicatedKey) {
  76. return errors.New("group mcp already exists")
  77. }
  78. return err
  79. }
  80. // UpdateGroupMCP updates an existing GroupMCP
  81. func UpdateGroupMCP(mcp *GroupMCP) (err error) {
  82. defer func() {
  83. if err == nil {
  84. if err := CacheDeleteGroupMCP(mcp.GroupID, mcp.ID); err != nil {
  85. log.Error("cache delete group mcp error: " + err.Error())
  86. }
  87. }
  88. }()
  89. selects := []string{
  90. "name",
  91. "proxy_config",
  92. "openapi_config",
  93. "description",
  94. }
  95. if mcp.Type != "" {
  96. selects = append(selects, "type")
  97. }
  98. if mcp.Status != 0 {
  99. selects = append(selects, "status")
  100. }
  101. result := DB.
  102. Select(selects).
  103. Where("id = ? AND group_id = ?", mcp.ID, mcp.GroupID).
  104. Updates(mcp)
  105. return HandleUpdateResult(result, ErrGroupMCPNotFound)
  106. }
  107. func UpdateGroupMCPStatus(id, groupID string, status GroupMCPStatus) (err error) {
  108. defer func() {
  109. if err == nil {
  110. if err := CacheDeleteGroupMCP(groupID, id); err != nil {
  111. log.Error("cache delete group mcp error: " + err.Error())
  112. }
  113. }
  114. }()
  115. result := DB.Model(&GroupMCP{}).
  116. Where("id = ? AND group_id = ?", id, groupID).
  117. Update("status", status)
  118. return HandleUpdateResult(result, ErrGroupMCPNotFound)
  119. }
  120. func GetAllGroupMCPs(status GroupMCPStatus) ([]GroupMCP, error) {
  121. var mcps []GroupMCP
  122. tx := DB.Model(&GroupMCP{})
  123. if status != 0 {
  124. tx = tx.Where("status = ?", status)
  125. }
  126. err := tx.Find(&mcps).Error
  127. return mcps, err
  128. }
  129. // DeleteGroupMCP deletes a GroupMCP by ID and GroupID
  130. func DeleteGroupMCP(id, groupID string) (err error) {
  131. defer func() {
  132. if err == nil {
  133. if err := CacheDeleteGroupMCP(groupID, id); err != nil {
  134. log.Error("cache delete group mcp error: " + err.Error())
  135. }
  136. }
  137. }()
  138. if id == "" || groupID == "" {
  139. return errors.New("group mcp id or group id is empty")
  140. }
  141. result := DB.Where("id = ? AND group_id = ?", id, groupID).Delete(&GroupMCP{})
  142. return HandleUpdateResult(result, ErrGroupMCPNotFound)
  143. }
  144. // GetGroupMCPByID retrieves a GroupMCP by ID and GroupID
  145. func GetGroupMCPByID(id, groupID string) (GroupMCP, error) {
  146. var mcp GroupMCP
  147. if id == "" || groupID == "" {
  148. return mcp, errors.New("group mcp id or group id is empty")
  149. }
  150. err := DB.Where("id = ? AND group_id = ?", id, groupID).First(&mcp).Error
  151. return mcp, HandleNotFound(err, ErrGroupMCPNotFound)
  152. }
  153. // GetGroupMCPs retrieves GroupMCPs with pagination and filtering
  154. func GetGroupMCPs(
  155. groupID string,
  156. page, perPage int,
  157. id string,
  158. mcpType GroupMCPType,
  159. keyword string,
  160. status GroupMCPStatus,
  161. ) (mcps []GroupMCP, total int64, err error) {
  162. if groupID == "" {
  163. return nil, 0, errors.New("group id is empty")
  164. }
  165. tx := DB.Model(&GroupMCP{}).Where("group_id = ?", groupID)
  166. if id != "" {
  167. tx = tx.Where("id = ?", id)
  168. }
  169. if status != 0 {
  170. tx = tx.Where("status = ?", status)
  171. }
  172. if mcpType != "" {
  173. tx = tx.Where("type = ?", mcpType)
  174. }
  175. if keyword != "" {
  176. var (
  177. conditions []string
  178. values []any
  179. )
  180. if id == "" {
  181. if !common.UsingSQLite {
  182. conditions = append(conditions, "id ILIKE ?")
  183. values = append(values, "%"+keyword+"%")
  184. } else {
  185. conditions = append(conditions, "id LIKE ?")
  186. values = append(values, "%"+keyword+"%")
  187. }
  188. }
  189. if !common.UsingSQLite {
  190. conditions = append(conditions, "name ILIKE ?")
  191. values = append(values, "%"+keyword+"%")
  192. } else {
  193. conditions = append(conditions, "name LIKE ?")
  194. values = append(values, "%"+keyword+"%")
  195. }
  196. if !common.UsingSQLite {
  197. conditions = append(conditions, "description ILIKE ?")
  198. values = append(values, "%"+keyword+"%")
  199. } else {
  200. conditions = append(conditions, "description LIKE ?")
  201. values = append(values, "%"+keyword+"%")
  202. }
  203. if len(conditions) > 0 {
  204. tx = tx.Where(fmt.Sprintf("(%s)", strings.Join(conditions, " OR ")), values...)
  205. }
  206. }
  207. err = tx.Count(&total).Error
  208. if err != nil {
  209. return nil, 0, err
  210. }
  211. if total <= 0 {
  212. return nil, 0, nil
  213. }
  214. limit, offset := toLimitOffset(page, perPage)
  215. err = tx.
  216. Limit(limit).
  217. Offset(offset).
  218. Find(&mcps).
  219. Error
  220. return mcps, total, err
  221. }