groupmcp.go 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. package controller
  2. import (
  3. "fmt"
  4. "net/http"
  5. "strconv"
  6. "github.com/bytedance/sonic"
  7. "github.com/gin-gonic/gin"
  8. "github.com/labring/aiproxy/core/common/config"
  9. "github.com/labring/aiproxy/core/controller/utils"
  10. "github.com/labring/aiproxy/core/middleware"
  11. "github.com/labring/aiproxy/core/model"
  12. )
  13. type GroupMCPResponse struct {
  14. model.GroupMCP
  15. Endpoints MCPEndpoint `json:"endpoints"`
  16. }
  17. func (mcp *GroupMCPResponse) MarshalJSON() ([]byte, error) {
  18. type Alias GroupMCPResponse
  19. a := &struct {
  20. *Alias
  21. CreatedAt int64 `json:"created_at"`
  22. UpdateAt int64 `json:"update_at"`
  23. }{
  24. Alias: (*Alias)(mcp),
  25. CreatedAt: mcp.CreatedAt.UnixMilli(),
  26. UpdateAt: mcp.UpdateAt.UnixMilli(),
  27. }
  28. return sonic.Marshal(a)
  29. }
  30. func NewGroupMCPResponse(host string, mcp model.GroupMCP) GroupMCPResponse {
  31. ep := MCPEndpoint{}
  32. switch mcp.Type {
  33. case model.GroupMCPTypeProxySSE,
  34. model.GroupMCPTypeProxyStreamable,
  35. model.GroupMCPTypeOpenAPI:
  36. groupMCPHost := config.GetGroupMCPHost()
  37. if groupMCPHost == "" {
  38. ep.Host = host
  39. ep.SSE = fmt.Sprintf("/mcp/group/%s/sse", mcp.ID)
  40. ep.StreamableHTTP = "/mcp/group/" + mcp.ID
  41. } else {
  42. ep.Host = fmt.Sprintf("%s.%s", mcp.ID, groupMCPHost)
  43. ep.SSE = "/sse"
  44. ep.StreamableHTTP = "/mcp"
  45. }
  46. }
  47. return GroupMCPResponse{
  48. GroupMCP: mcp,
  49. Endpoints: ep,
  50. }
  51. }
  52. func NewGroupMCPResponses(host string, mcps []model.GroupMCP) []GroupMCPResponse {
  53. responses := make([]GroupMCPResponse, len(mcps))
  54. for i, mcp := range mcps {
  55. responses[i] = NewGroupMCPResponse(host, mcp)
  56. }
  57. return responses
  58. }
  59. // GetGroupMCPs godoc
  60. //
  61. // @Summary Get Group MCPs
  62. // @Description Get a list of Group MCPs with pagination and filtering
  63. // @Tags mcp
  64. // @Produce json
  65. // @Security ApiKeyAuth
  66. // @Param group path string true "Group ID"
  67. // @Param page query int false "Page number"
  68. // @Param per_page query int false "Items per page"
  69. // @Param id query string false "MCP id"
  70. // @Param type query string false "MCP type, mcp_proxy_sse, mcp_proxy_streamable, mcp_openapi"
  71. // @Param keyword query string false "Search keyword"
  72. // @Param status query int false "MCP status"
  73. // @Success 200 {object} middleware.APIResponse{data=[]GroupMCPResponse}
  74. // @Router /api/mcp/group/{group} [get]
  75. func GetGroupMCPs(c *gin.Context) {
  76. groupID := c.Param("group")
  77. if groupID == "" {
  78. middleware.ErrorResponse(c, http.StatusBadRequest, "Group ID is required")
  79. return
  80. }
  81. page, perPage := utils.ParsePageParams(c)
  82. id := c.Query("id")
  83. mcpType := model.GroupMCPType(c.Query("type"))
  84. keyword := c.Query("keyword")
  85. status, _ := strconv.Atoi(c.Query("status"))
  86. if status == 0 {
  87. status = int(model.GroupMCPStatusEnabled)
  88. }
  89. mcps, total, err := model.GetGroupMCPs(
  90. groupID,
  91. page,
  92. perPage,
  93. id,
  94. mcpType,
  95. keyword,
  96. model.GroupMCPStatus(status),
  97. )
  98. if err != nil {
  99. middleware.ErrorResponse(c, http.StatusInternalServerError, err.Error())
  100. return
  101. }
  102. middleware.SuccessResponse(c, gin.H{
  103. "mcps": NewGroupMCPResponses(c.Request.Host, mcps),
  104. "total": total,
  105. })
  106. }
  107. // GetAllGroupMCPs godoc
  108. //
  109. // @Summary Get all Group MCPs
  110. // @Description Get all Group MCPs with filtering
  111. // @Tags mcp
  112. // @Produce json
  113. // @Security ApiKeyAuth
  114. // @Param status query int false "MCP status"
  115. // @Success 200 {object} middleware.APIResponse{data=[]GroupMCPResponse}
  116. // @Router /api/mcp/group/all [get]
  117. func GetAllGroupMCPs(c *gin.Context) {
  118. status, _ := strconv.Atoi(c.Query("status"))
  119. if status == 0 {
  120. status = int(model.GroupMCPStatusEnabled)
  121. }
  122. mcps, err := model.GetAllGroupMCPs(model.GroupMCPStatus(status))
  123. if err != nil {
  124. middleware.ErrorResponse(c, http.StatusInternalServerError, err.Error())
  125. return
  126. }
  127. middleware.SuccessResponse(c, NewGroupMCPResponses(c.Request.Host, mcps))
  128. }
  129. // GetGroupMCPByID godoc
  130. //
  131. // @Summary Get Group MCP by ID
  132. // @Description Get a specific Group MCP by its ID and Group ID
  133. // @Tags mcp
  134. // @Produce json
  135. // @Security ApiKeyAuth
  136. // @Param id path string true "MCP ID"
  137. // @Param group path string true "Group ID"
  138. // @Success 200 {object} middleware.APIResponse{data=GroupMCPResponse}
  139. // @Router /api/mcp/group/{group}/{id} [get]
  140. func GetGroupMCPByID(c *gin.Context) {
  141. id := c.Param("id")
  142. groupID := c.Param("group")
  143. if id == "" || groupID == "" {
  144. middleware.ErrorResponse(c, http.StatusBadRequest, "MCP ID and Group ID are required")
  145. return
  146. }
  147. mcp, err := model.GetGroupMCPByID(id, groupID)
  148. if err != nil {
  149. middleware.ErrorResponse(c, http.StatusNotFound, err.Error())
  150. return
  151. }
  152. middleware.SuccessResponse(c, NewGroupMCPResponse(c.Request.Host, mcp))
  153. }
  154. // CreateGroupMCP godoc
  155. //
  156. // @Summary Create Group MCP
  157. // @Description Create a new Group MCP
  158. // @Tags mcp
  159. // @Accept json
  160. // @Produce json
  161. // @Security ApiKeyAuth
  162. // @Param group path string true "Group ID"
  163. // @Param mcp body model.GroupMCP true "Group MCP object"
  164. // @Success 200 {object} middleware.APIResponse{data=GroupMCPResponse}
  165. // @Router /api/mcp/group/{group} [post]
  166. func CreateGroupMCP(c *gin.Context) {
  167. groupID := c.Param("group")
  168. if groupID == "" {
  169. middleware.ErrorResponse(c, http.StatusBadRequest, "Group ID is required")
  170. return
  171. }
  172. var mcp model.GroupMCP
  173. if err := c.ShouldBindJSON(&mcp); err != nil {
  174. middleware.ErrorResponse(c, http.StatusBadRequest, err.Error())
  175. return
  176. }
  177. mcp.GroupID = groupID
  178. if err := model.CreateGroupMCP(&mcp); err != nil {
  179. middleware.ErrorResponse(c, http.StatusInternalServerError, err.Error())
  180. return
  181. }
  182. middleware.SuccessResponse(c, NewGroupMCPResponse(c.Request.Host, mcp))
  183. }
  184. // UpdateGroupMCP godoc
  185. //
  186. // @Summary Update Group MCP
  187. // @Description Update an existing Group MCP
  188. // @Tags mcp
  189. // @Accept json
  190. // @Produce json
  191. // @Security ApiKeyAuth
  192. // @Param id path string true "MCP ID"
  193. // @Param group path string true "Group ID"
  194. // @Param mcp body model.GroupMCP true "Group MCP object"
  195. // @Success 200 {object} middleware.APIResponse{data=GroupMCPResponse}
  196. // @Router /api/mcp/group/{group}/{id} [put]
  197. func UpdateGroupMCP(c *gin.Context) {
  198. id := c.Param("id")
  199. groupID := c.Param("group")
  200. if id == "" || groupID == "" {
  201. middleware.ErrorResponse(c, http.StatusBadRequest, "MCP ID and Group ID are required")
  202. return
  203. }
  204. var mcp model.GroupMCP
  205. if err := c.ShouldBindJSON(&mcp); err != nil {
  206. middleware.ErrorResponse(c, http.StatusBadRequest, err.Error())
  207. return
  208. }
  209. mcp.ID = id
  210. mcp.GroupID = groupID
  211. if err := model.UpdateGroupMCP(&mcp); err != nil {
  212. middleware.ErrorResponse(c, http.StatusInternalServerError, err.Error())
  213. return
  214. }
  215. middleware.SuccessResponse(c, NewGroupMCPResponse(c.Request.Host, mcp))
  216. }
  217. type UpdateGroupMCPStatusRequest struct {
  218. Status model.GroupMCPStatus `json:"status"`
  219. }
  220. // UpdateGroupMCPStatus godoc
  221. //
  222. // @Summary Update Group MCP status
  223. // @Description Update the status of a Group MCP
  224. // @Tags mcp
  225. // @Accept json
  226. // @Produce json
  227. // @Security ApiKeyAuth
  228. // @Param id path string true "MCP ID"
  229. // @Param group path string true "Group ID"
  230. // @Param status body UpdateGroupMCPStatusRequest true "MCP status"
  231. // @Success 200 {object} middleware.APIResponse
  232. // @Router /api/mcp/group/{group}/{id}/status [post]
  233. func UpdateGroupMCPStatus(c *gin.Context) {
  234. id := c.Param("id")
  235. groupID := c.Param("group")
  236. if id == "" || groupID == "" {
  237. middleware.ErrorResponse(c, http.StatusBadRequest, "MCP ID and Group ID are required")
  238. return
  239. }
  240. var status UpdateGroupMCPStatusRequest
  241. if err := c.ShouldBindJSON(&status); err != nil {
  242. middleware.ErrorResponse(c, http.StatusBadRequest, err.Error())
  243. return
  244. }
  245. if err := model.UpdateGroupMCPStatus(id, groupID, status.Status); err != nil {
  246. middleware.ErrorResponse(c, http.StatusInternalServerError, err.Error())
  247. return
  248. }
  249. middleware.SuccessResponse(c, nil)
  250. }
  251. // DeleteGroupMCP godoc
  252. //
  253. // @Summary Delete Group MCP
  254. // @Description Delete a Group MCP by ID and Group ID
  255. // @Tags mcp
  256. // @Produce json
  257. // @Security ApiKeyAuth
  258. // @Param id path string true "MCP ID"
  259. // @Param group path string true "Group ID"
  260. // @Success 200 {object} middleware.APIResponse
  261. // @Router /api/mcp/group/{group}/{id} [delete]
  262. func DeleteGroupMCP(c *gin.Context) {
  263. id := c.Param("id")
  264. groupID := c.Param("group")
  265. if id == "" || groupID == "" {
  266. middleware.ErrorResponse(c, http.StatusBadRequest, "MCP ID and Group ID are required")
  267. return
  268. }
  269. if err := model.DeleteGroupMCP(id, groupID); err != nil {
  270. middleware.ErrorResponse(c, http.StatusInternalServerError, err.Error())
  271. return
  272. }
  273. middleware.SuccessResponse(c, nil)
  274. }