mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-06-29 15:31:05 +08:00
feat: add Go MCP server delete API (#15262)
## What #15240 Implementation for DELETE /api/v1/mcp/servers/:mcp_id
This commit is contained in:
committed by
GitHub
parent
09e91a8e61
commit
faa9c5469e
43
.github/workflows/tests.yml
vendored
43
.github/workflows/tests.yml
vendored
@@ -171,9 +171,46 @@ jobs:
|
||||
RUNNER_NUM=$(sudo docker inspect $(hostname) --format '{{index .Config.Labels "com.docker.compose.container-number"}}' 2>/dev/null || true)
|
||||
RUNNER_NUM=${RUNNER_NUM:-1}
|
||||
|
||||
# Per-runner base plus per-workflow-run offset avoids port clashes when
|
||||
# multiple CI jobs share the same self-hosted runner concurrently.
|
||||
PORT_OFFSET=$(( (GITHUB_RUN_ID % 400) + RUNNER_NUM * 10 ))
|
||||
# Per-runner seed plus per-workflow-run offset avoids most clashes when
|
||||
# multiple CI jobs share the same self-hosted runner concurrently. Probe
|
||||
# the final host ports too, because stale compose projects can still hold
|
||||
# a deterministic port from a previous run.
|
||||
PORT_BASES=(1200 1201 23817 23820 5432 5455 9000 9001 6379 6380 6601 9380 9381 9382 9384 9383 9385 80 443)
|
||||
MAX_PORT_OFFSET=$((65000 - 23820))
|
||||
PORT_OFFSET=$(( (GITHUB_RUN_ID % 4000) + RUNNER_NUM * 1000 ))
|
||||
OFFSET_FOUND=false
|
||||
|
||||
port_offset_available() {
|
||||
local offset=$1
|
||||
local base port
|
||||
for base in "${PORT_BASES[@]}"; do
|
||||
port=$((base + offset))
|
||||
if ss -ltnH "sport = :${port}" | grep -q .; then
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
for ATTEMPT in $(seq 0 9); do
|
||||
CANDIDATE_OFFSET=$(( (PORT_OFFSET + ATTEMPT * 4000) % MAX_PORT_OFFSET ))
|
||||
if [ "${CANDIDATE_OFFSET}" -lt 1000 ]; then
|
||||
CANDIDATE_OFFSET=$((CANDIDATE_OFFSET + 1000))
|
||||
fi
|
||||
|
||||
if port_offset_available "${CANDIDATE_OFFSET}"; then
|
||||
PORT_OFFSET=${CANDIDATE_OFFSET}
|
||||
OFFSET_FOUND=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "${OFFSET_FOUND}" != "true" ]; then
|
||||
echo "Failed to find a free host port range for docker compose" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Using host port offset ${PORT_OFFSET}"
|
||||
ES_PORT=$((1200 + PORT_OFFSET))
|
||||
OS_PORT=$((1201 + PORT_OFFSET))
|
||||
INFINITY_THRIFT_PORT=$((23817 + PORT_OFFSET))
|
||||
|
||||
@@ -16,7 +16,13 @@
|
||||
|
||||
package dao
|
||||
|
||||
import "ragflow/internal/entity"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"ragflow/internal/entity"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// MCPServerDAO MCP server data access object.
|
||||
type MCPServerDAO struct{}
|
||||
@@ -26,6 +32,18 @@ func NewMCPServerDAO() *MCPServerDAO {
|
||||
return &MCPServerDAO{}
|
||||
}
|
||||
|
||||
// GetByID returns an MCP server by ID.
|
||||
func (dao *MCPServerDAO) GetByID(id string) (*entity.MCPServer, error) {
|
||||
var server entity.MCPServer
|
||||
if err := DB.Where("id = ?", id).First(&server).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &server, nil
|
||||
}
|
||||
|
||||
// ExistsByNameAndTenant returns whether an MCP server name already exists for a tenant.
|
||||
func (dao *MCPServerDAO) ExistsByNameAndTenant(name, tenantID string) (bool, error) {
|
||||
var count int64
|
||||
@@ -41,3 +59,12 @@ func (dao *MCPServerDAO) ExistsByNameAndTenant(name, tenantID string) (bool, err
|
||||
func (dao *MCPServerDAO) CreateMCPServer(server *entity.MCPServer) error {
|
||||
return DB.Create(server).Error
|
||||
}
|
||||
|
||||
// DeleteMCPServer deletes an MCP server owned by a tenant.
|
||||
func (dao *MCPServerDAO) DeleteMCPServer(id, tenantID string) (bool, error) {
|
||||
result := DB.Where("id = ? AND tenant_id = ?", id, tenantID).Delete(&entity.MCPServer{})
|
||||
if result.Error != nil {
|
||||
return false, result.Error
|
||||
}
|
||||
return result.RowsAffected > 0, nil
|
||||
}
|
||||
|
||||
@@ -63,3 +63,24 @@ func (h *MCPHandler) CreateMCPServer(c *gin.Context) {
|
||||
"data": result,
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteMCPServer deletes an MCP server for the current user.
|
||||
func (h *MCPHandler) DeleteMCPServer(c *gin.Context) {
|
||||
user, errorCode, errorMessage := GetUser(c)
|
||||
if errorCode != common.CodeSuccess {
|
||||
jsonError(c, errorCode, errorMessage)
|
||||
return
|
||||
}
|
||||
|
||||
result, code, err := h.mcpService.DeleteMCPServer(user.ID, c.Param("mcp_id"))
|
||||
if err != nil {
|
||||
jsonError(c, code, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": common.CodeSuccess,
|
||||
"message": "success",
|
||||
"data": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -260,6 +260,7 @@ func (r *Router) Setup(engine *gin.Engine) {
|
||||
mcp := v1.Group("/mcp")
|
||||
{
|
||||
mcp.POST("/servers", r.mcpHandler.CreateMCPServer)
|
||||
mcp.DELETE("/servers/:mcp_id", r.mcpHandler.DeleteMCPServer)
|
||||
}
|
||||
|
||||
// Skill search routes
|
||||
|
||||
@@ -127,6 +127,31 @@ func (s *MCPService) CreateMCPServer(tenantID string, req CreateMCPServerRequest
|
||||
}, common.CodeSuccess, nil
|
||||
}
|
||||
|
||||
// DeleteMCPServer deletes an MCP server owned by a tenant.
|
||||
func (s *MCPService) DeleteMCPServer(tenantID, mcpID string) (bool, common.ErrorCode, error) {
|
||||
server, err := s.mcpServerDAO.GetByID(mcpID)
|
||||
if err != nil {
|
||||
return false, common.CodeServerError, fmt.Errorf("failed to get MCP server %s: %w", mcpID, err)
|
||||
}
|
||||
if server == nil || server.TenantID != tenantID {
|
||||
return false, common.CodeDataError, mcpServerNotFoundError(mcpID, tenantID)
|
||||
}
|
||||
|
||||
deleted, err := s.mcpServerDAO.DeleteMCPServer(mcpID, tenantID)
|
||||
if err != nil {
|
||||
return false, common.CodeServerError, err
|
||||
}
|
||||
if !deleted {
|
||||
return false, common.CodeDataError, mcpServerNotFoundError(mcpID, tenantID)
|
||||
}
|
||||
|
||||
return true, common.CodeSuccess, nil
|
||||
}
|
||||
|
||||
func mcpServerNotFoundError(mcpID, tenantID string) error {
|
||||
return fmt.Errorf("Cannot find MCP server %s for user %s", mcpID, tenantID)
|
||||
}
|
||||
|
||||
func isValidMCPServerType(serverType string) bool {
|
||||
return serverType == mcpServerTypeSSE || serverType == mcpServerTypeStreamableHTTP
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user