Files
Go-Web-Template/server/api/v1/system/mcp.go
2026-04-08 12:19:24 +08:00

168 lines
4.6 KiB
Go

package system
import (
"strings"
"github.com/flipped-aurora/gin-vue-admin/server/global"
mcpTool "github.com/flipped-aurora/gin-vue-admin/server/mcp"
"github.com/flipped-aurora/gin-vue-admin/server/mcp/client"
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
systemReq "github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
"github.com/gin-gonic/gin"
"github.com/mark3labs/mcp-go/mcp"
)
type McpApi struct{}
func (a *McpApi) CreateTool(c *gin.Context) {
var info systemReq.McpToolTemplateRequest
if err := c.ShouldBindJSON(&info); err != nil {
response.FailWithMessage(err.Error(), c)
return
}
toolFilePath, err := mcpService.CreateToolTemplate(c.Request.Context(), info)
if err != nil {
response.FailWithMessage("创建失败", c)
global.GVA_LOG.Error(err.Error())
return
}
response.OkWithMessage("创建成功,MCP Tool路径:"+toolFilePath, c)
}
func (a *McpApi) Status(c *gin.Context) {
response.OkWithData(gin.H{
"status": mcpTool.GetManagedStandaloneStatus(c.Request.Context()),
"mcpServerConfig": buildMCPServerConfig(),
}, c)
}
func (a *McpApi) Start(c *gin.Context) {
status, err := mcpTool.StartManagedStandalone(c.Request.Context())
if err != nil {
response.FailWithDetailed(gin.H{
"status": status,
"mcpServerConfig": buildMCPServerConfig(),
}, err.Error(), c)
return
}
response.OkWithDetailed(gin.H{
"status": status,
"mcpServerConfig": buildMCPServerConfig(),
}, "MCP独立服务已启动", c)
}
func (a *McpApi) Stop(c *gin.Context) {
status, err := mcpTool.StopManagedStandalone(c.Request.Context())
if err != nil {
response.FailWithDetailed(gin.H{
"status": status,
"mcpServerConfig": buildMCPServerConfig(),
}, err.Error(), c)
return
}
response.OkWithDetailed(gin.H{
"status": status,
"mcpServerConfig": buildMCPServerConfig(),
}, "MCP独立服务已停用", c)
}
func (a *McpApi) List(c *gin.Context) {
testClient, err := client.NewClient(mcpTool.ResolveMCPServiceURL(), "testClient", "v1.0.0", mcpServerName(), incomingMCPHeaders(c))
if err != nil {
response.FailWithDetailed(gin.H{
"status": mcpTool.GetManagedStandaloneStatus(c.Request.Context()),
"mcpServerConfig": buildMCPServerConfig(),
}, "连接MCP服务失败:"+err.Error(), c)
return
}
defer testClient.Close()
list, err := testClient.ListTools(c.Request.Context(), mcp.ListToolsRequest{})
if err != nil {
response.FailWithDetailed(gin.H{
"status": mcpTool.GetManagedStandaloneStatus(c.Request.Context()),
"mcpServerConfig": buildMCPServerConfig(),
}, "获取工具列表失败:"+err.Error(), c)
return
}
response.OkWithData(gin.H{
"status": mcpTool.GetManagedStandaloneStatus(c.Request.Context()),
"mcpServerConfig": buildMCPServerConfig(),
"list": list,
}, c)
}
func (a *McpApi) Test(c *gin.Context) {
var testRequest struct {
Name string `json:"name" binding:"required"`
Arguments map[string]interface{} `json:"arguments" binding:"required"`
}
if err := c.ShouldBindJSON(&testRequest); err != nil {
response.FailWithMessage("参数解析失败:"+err.Error(), c)
return
}
testClient, err := client.NewClient(mcpTool.ResolveMCPServiceURL(), "testClient", "v1.0.0", mcpServerName(), incomingMCPHeaders(c))
if err != nil {
response.FailWithMessage("连接MCP服务失败:"+err.Error(), c)
return
}
defer testClient.Close()
callRequest := mcp.CallToolRequest{}
callRequest.Params.Name = testRequest.Name
callRequest.Params.Arguments = testRequest.Arguments
result, err := testClient.CallTool(c.Request.Context(), callRequest)
if err != nil {
response.FailWithMessage("工具调用失败:"+err.Error(), c)
return
}
if len(result.Content) == 0 {
response.FailWithMessage("工具未返回任何内容", c)
return
}
response.OkWithData(result.Content, c)
}
func incomingMCPHeaders(c *gin.Context) map[string]string {
headerName := mcpTool.ConfiguredAuthHeader()
headerValue := c.GetHeader(headerName)
if headerValue == "" {
return nil
}
return map[string]string{
headerName: headerValue,
}
}
func buildMCPServerConfig() map[string]interface{} {
baseURL := mcpTool.ResolveMCPServiceURL()
authHeader := mcpTool.ConfiguredAuthHeader()
serverName := mcpServerName()
return map[string]interface{}{
"mcpServers": map[string]interface{}{
serverName: map[string]interface{}{
"url": baseURL,
"headers": map[string]string{
authHeader: "${YOUR_GVA_TOKEN}",
},
},
},
}
}
func mcpServerName() string {
if name := strings.TrimSpace(global.GVA_CONFIG.MCP.Name); name != "" {
return name
}
return "gva"
}