| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463 |
- package controller
- import (
- "encoding/json"
- "fmt"
- "net/http"
- "strconv"
- "github.com/bytedance/sonic"
- "github.com/gin-gonic/gin"
- "github.com/labring/aiproxy/core/common/config"
- "github.com/labring/aiproxy/core/controller/utils"
- "github.com/labring/aiproxy/core/middleware"
- "github.com/labring/aiproxy/core/model"
- )
- type MCPEndpoint struct {
- Host string `json:"host"`
- SSE string `json:"sse"`
- StreamableHTTP string `json:"streamable_http"`
- }
- type PublicMCPResponse struct {
- model.PublicMCP
- Endpoints MCPEndpoint `json:"endpoints"`
- }
- func (mcp *PublicMCPResponse) MarshalJSON() ([]byte, error) {
- type Alias PublicMCPResponse
- a := &struct {
- *Alias
- CreatedAt int64 `json:"created_at"`
- UpdateAt int64 `json:"update_at"`
- }{
- Alias: (*Alias)(mcp),
- }
- if !mcp.CreatedAt.IsZero() {
- a.CreatedAt = mcp.CreatedAt.UnixMilli()
- }
- if !mcp.UpdateAt.IsZero() {
- a.UpdateAt = mcp.UpdateAt.UnixMilli()
- }
- return sonic.Marshal(a)
- }
- func NewPublicMCPEndpoint(host string, mcp model.PublicMCP) MCPEndpoint {
- ep := MCPEndpoint{}
- switch mcp.Type {
- case model.PublicMCPTypeProxySSE,
- model.PublicMCPTypeProxyStreamable,
- model.PublicMCPTypeEmbed,
- model.PublicMCPTypeOpenAPI:
- publicMCPHost := config.GetPublicMCPHost()
- if publicMCPHost == "" {
- ep.Host = host
- if defaultHost := config.GetDefaultMCPHost(); defaultHost != "" {
- ep.Host = defaultHost
- }
- ep.SSE = fmt.Sprintf("/mcp/public/%s/sse", mcp.ID)
- ep.StreamableHTTP = "/mcp/public/" + mcp.ID
- } else {
- ep.Host = fmt.Sprintf("%s.%s", mcp.ID, publicMCPHost)
- ep.SSE = "/sse"
- ep.StreamableHTTP = "/mcp"
- }
- case model.PublicMCPTypeDocs:
- }
- return ep
- }
- func NewPublicMCPResponse(host string, mcp model.PublicMCP) PublicMCPResponse {
- return PublicMCPResponse{
- PublicMCP: mcp,
- Endpoints: NewPublicMCPEndpoint(host, mcp),
- }
- }
- func NewPublicMCPResponses(host string, mcps []model.PublicMCP) []PublicMCPResponse {
- responses := make([]PublicMCPResponse, len(mcps))
- for i, mcp := range mcps {
- responses[i] = NewPublicMCPResponse(host, mcp)
- }
- 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
- // @Description Get a list of MCPs with pagination and filtering
- // @Tags mcp
- // @Produce json
- // @Security ApiKeyAuth
- // @Param page query int false "Page number"
- // @Param per_page query int false "Items per page"
- // @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/publics/ [get]
- func GetPublicMCPs(c *gin.Context) {
- page, perPage := utils.ParsePageParams(c)
- 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,
- id,
- mcpTypes,
- keyword,
- model.PublicMCPStatus(status),
- )
- if err != nil {
- middleware.ErrorResponse(c, http.StatusInternalServerError, err.Error())
- return
- }
- middleware.SuccessResponse(c, gin.H{
- "mcps": NewPublicMCPResponses(c.Request.Host, mcps),
- "total": total,
- })
- }
- // GetAllPublicMCPs godoc
- //
- // @Summary Get all MCPs
- // @Description Get all MCPs with filtering
- // @Tags mcp
- // @Produce json
- // @Security ApiKeyAuth
- // @Param status query int false "MCP status"
- // @Success 200 {object} middleware.APIResponse{data=[]PublicMCPResponse}
- // @Router /api/mcp/publics/all [get]
- func GetAllPublicMCPs(c *gin.Context) {
- status, _ := strconv.Atoi(c.Query("status"))
- mcps, err := model.GetAllPublicMCPs(model.PublicMCPStatus(status))
- if err != nil {
- middleware.ErrorResponse(c, http.StatusInternalServerError, err.Error())
- return
- }
- middleware.SuccessResponse(c, NewPublicMCPResponses(c.Request.Host, mcps))
- }
- // GetPublicMCPByID godoc
- //
- // @Summary Get MCP by ID
- // @Description Get a specific MCP by its ID
- // @Tags mcp
- // @Produce json
- // @Security ApiKeyAuth
- // @Param id path string true "MCP ID"
- // @Success 200 {object} middleware.APIResponse{data=PublicMCPResponse}
- // @Router /api/mcp/public/{id} [get]
- func GetPublicMCPByID(c *gin.Context) {
- id := c.Param("id")
- if id == "" {
- middleware.ErrorResponse(c, http.StatusBadRequest, "MCP ID is required")
- return
- }
- mcp, err := model.GetPublicMCPByID(id)
- if err != nil {
- middleware.ErrorResponse(c, http.StatusNotFound, err.Error())
- return
- }
- middleware.SuccessResponse(c, NewPublicMCPResponse(c.Request.Host, mcp))
- }
- // CreatePublicMCP godoc
- //
- // @Summary Create MCP
- // @Description Create a new MCP
- // @Tags mcp
- // @Accept json
- // @Produce json
- // @Security ApiKeyAuth
- // @Param mcp body model.PublicMCP true "MCP object"
- // @Success 200 {object} middleware.APIResponse{data=PublicMCPResponse}
- // @Router /api/mcp/public/ [post]
- func CreatePublicMCP(c *gin.Context) {
- var mcp model.PublicMCP
- if err := c.ShouldBindJSON(&mcp); err != nil {
- middleware.ErrorResponse(c, http.StatusBadRequest, err.Error())
- return
- }
- if err := model.CreatePublicMCP(&mcp); err != nil {
- middleware.ErrorResponse(c, http.StatusInternalServerError, err.Error())
- return
- }
- middleware.SuccessResponse(c, NewPublicMCPResponse(c.Request.Host, mcp))
- }
- type SavePublicMCPRequest struct {
- model.PublicMCP
- CreatedAt json.RawMessage `json:"created_at"`
- UpdateAt json.RawMessage `json:"update_at"`
- }
- // SavePublicMCP godoc
- //
- // @Summary Save MCP
- // @Description Save a MCP
- // @Tags mcp
- // @Accept json
- // @Produce json
- // @Security ApiKeyAuth
- // @Param id path string true "MCP ID"
- // @Param mcp body model.PublicMCP true "MCP object"
- // @Success 200 {object} middleware.APIResponse{data=PublicMCPResponse}
- // @Router /api/mcp/public/{id} [put]
- func SavePublicMCP(c *gin.Context) {
- id := c.Param("id")
- if id == "" {
- middleware.ErrorResponse(c, http.StatusBadRequest, "MCP ID is required")
- return
- }
- var mcp SavePublicMCPRequest
- if err := c.ShouldBindJSON(&mcp); err != nil {
- middleware.ErrorResponse(c, http.StatusBadRequest, err.Error())
- return
- }
- mcp.ID = id
- if err := model.SavePublicMCP(&mcp.PublicMCP); err != nil {
- middleware.ErrorResponse(c, http.StatusInternalServerError, err.Error())
- return
- }
- middleware.SuccessResponse(c, NewPublicMCPResponse(c.Request.Host, mcp.PublicMCP))
- }
- // SavePublicMCPs godoc
- //
- // @Summary Save MCPs
- // @Description Save a list of MCPs
- // @Tags mcp
- // @Accept json
- // @Produce json
- // @Security ApiKeyAuth
- // @Param mcp body []model.PublicMCP true "MCP object"
- // @Success 200 {object} middleware.APIResponse
- // @Router /api/mcp/publics/ [post]
- func SavePublicMCPs(c *gin.Context) {
- var mcps []SavePublicMCPRequest
- if err := c.ShouldBindJSON(&mcps); err != nil {
- middleware.ErrorResponse(c, http.StatusBadRequest, err.Error())
- return
- }
- pmcps := make([]model.PublicMCP, len(mcps))
- for i, mcp := range mcps {
- pmcps[i] = mcp.PublicMCP
- }
- if err := model.SavePublicMCPs(pmcps); err != nil {
- middleware.ErrorResponse(c, http.StatusInternalServerError, err.Error())
- return
- }
- middleware.SuccessResponse(c, nil)
- }
- type UpdatePublicMCPStatusRequest struct {
- Status model.PublicMCPStatus `json:"status"`
- }
- // UpdatePublicMCPStatus godoc
- //
- // @Summary Update MCP status
- // @Description Update the status of an MCP
- // @Tags mcp
- // @Accept json
- // @Produce json
- // @Security ApiKeyAuth
- // @Param id path string true "MCP ID"
- // @Param status body UpdatePublicMCPStatusRequest true "MCP status"
- // @Success 200 {object} middleware.APIResponse
- // @Router /api/mcp/public/{id}/status [post]
- func UpdatePublicMCPStatus(c *gin.Context) {
- id := c.Param("id")
- if id == "" {
- middleware.ErrorResponse(c, http.StatusBadRequest, "MCP ID is required")
- return
- }
- var status UpdatePublicMCPStatusRequest
- if err := c.ShouldBindJSON(&status); err != nil {
- middleware.ErrorResponse(c, http.StatusBadRequest, err.Error())
- return
- }
- if err := model.UpdatePublicMCPStatus(id, status.Status); err != nil {
- middleware.ErrorResponse(c, http.StatusInternalServerError, err.Error())
- return
- }
- middleware.SuccessResponse(c, nil)
- }
- // UpdatePublicMCP godoc
- //
- // @Summary Update MCP
- // @Description Update an existing MCP
- // @Tags mcp
- // @Accept json
- // @Produce json
- // @Security ApiKeyAuth
- // @Param id path string true "MCP ID"
- // @Param mcp body model.PublicMCP true "MCP object"
- // @Success 200 {object} middleware.APIResponse{data=PublicMCPResponse}
- // @Router /api/mcp/public/{id} [post]
- func UpdatePublicMCP(c *gin.Context) {
- id := c.Param("id")
- if id == "" {
- middleware.ErrorResponse(c, http.StatusBadRequest, "MCP ID is required")
- return
- }
- var mcp model.PublicMCP
- if err := c.ShouldBindJSON(&mcp); err != nil {
- middleware.ErrorResponse(c, http.StatusBadRequest, err.Error())
- return
- }
- mcp.ID = id
- if err := model.UpdatePublicMCP(&mcp); err != nil {
- middleware.ErrorResponse(c, http.StatusInternalServerError, err.Error())
- return
- }
- middleware.SuccessResponse(c, NewPublicMCPResponse(c.Request.Host, mcp))
- }
- // DeletePublicMCP godoc
- //
- // @Summary Delete MCP
- // @Description Delete an MCP by ID
- // @Tags mcp
- // @Produce json
- // @Security ApiKeyAuth
- // @Param id path string true "MCP ID"
- // @Success 200 {object} middleware.APIResponse
- // @Router /api/mcp/public/{id} [delete]
- func DeletePublicMCP(c *gin.Context) {
- id := c.Param("id")
- if id == "" {
- middleware.ErrorResponse(c, http.StatusBadRequest, "MCP ID is required")
- return
- }
- if err := model.DeletePublicMCP(id); err != nil {
- middleware.ErrorResponse(c, http.StatusInternalServerError, err.Error())
- return
- }
- middleware.SuccessResponse(c, nil)
- }
- // GetGroupPublicMCPReusingParam godoc
- //
- // @Summary Get group MCP reusing parameters
- // @Description Get reusing parameters for a specific group and MCP
- // @Tags mcp
- // @Produce json
- // @Security ApiKeyAuth
- // @Param id path string true "MCP ID"
- // @Param group path string true "Group ID"
- // @Success 200 {object} middleware.APIResponse{data=model.PublicMCPReusingParam}
- // @Router /api/mcp/public/{id}/group/{group}/params [get]
- func GetGroupPublicMCPReusingParam(c *gin.Context) {
- mcpID := c.Param("id")
- groupID := c.Param("group")
- if mcpID == "" || groupID == "" {
- middleware.ErrorResponse(c, http.StatusBadRequest, "MCP ID and Group ID are required")
- return
- }
- param, err := model.GetPublicMCPReusingParam(mcpID, groupID)
- if err != nil {
- middleware.ErrorResponse(c, http.StatusNotFound, err.Error())
- return
- }
- middleware.SuccessResponse(c, param)
- }
- // SaveGroupPublicMCPReusingParam godoc
- //
- // @Summary Create or update group MCP reusing parameters
- // @Description Create or update reusing parameters for a specific group and MCP
- // @Tags mcp
- // @Accept json
- // @Produce json
- // @Security ApiKeyAuth
- // @Param id path string true "MCP ID"
- // @Param group path string true "Group ID"
- // @Param params body model.PublicMCPReusingParam true "Reusing parameters"
- // @Success 200 {object} middleware.APIResponse
- // @Router /api/mcp/public/{id}/group/{group}/params [post]
- func SaveGroupPublicMCPReusingParam(c *gin.Context) {
- mcpID := c.Param("id")
- groupID := c.Param("group")
- if mcpID == "" || groupID == "" {
- middleware.ErrorResponse(c, http.StatusBadRequest, "MCP ID and Group ID are required")
- return
- }
- var param model.PublicMCPReusingParam
- if err := c.ShouldBindJSON(¶m); err != nil {
- middleware.ErrorResponse(c, http.StatusBadRequest, err.Error())
- return
- }
- param.MCPID = mcpID
- param.GroupID = groupID
- if err := model.SavePublicMCPReusingParam(¶m); err != nil {
- middleware.ErrorResponse(c, http.StatusInternalServerError, err.Error())
- return
- }
- middleware.SuccessResponse(c, param)
- }
|