Add MCP tool catalog functionality and validation
- Implement AnyCatalog method in MCPController to list MCP tools with detailed information. - Introduce MCPToolCatalogResponse struct for tool catalog responses. - Create ToolCatalogService to handle tool listing and validation of tool codes. - Enhance skill definition validation to include tool code validation against the catalog.
This commit is contained in:
@@ -24,6 +24,29 @@ func (c *MCPController) AnyList_servers() *web.JsonResult {
|
|||||||
return web.JsonData(response.BuildMCPServerInfoResponses(services.MCPDebugService.ListServers()))
|
return web.JsonData(response.BuildMCPServerInfoResponses(services.MCPDebugService.ListServers()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *MCPController) AnyCatalog() *web.JsonResult {
|
||||||
|
if _, err := services.AuthService.RequirePermission(c.Ctx, constants.PermissionMCPView); err != nil {
|
||||||
|
return web.JsonError(err)
|
||||||
|
}
|
||||||
|
items, err := services.ToolCatalogService.ListMCPTools(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
return web.JsonError(err)
|
||||||
|
}
|
||||||
|
ret := make([]response.MCPToolCatalogResponse, 0, len(items))
|
||||||
|
for _, item := range items {
|
||||||
|
ret = append(ret, response.MCPToolCatalogResponse{
|
||||||
|
ToolCode: item.ToolCode,
|
||||||
|
ServerCode: item.ServerCode,
|
||||||
|
ToolName: item.ToolName,
|
||||||
|
Title: item.Title,
|
||||||
|
Description: item.Description,
|
||||||
|
InputSchema: item.InputSchema,
|
||||||
|
OutputSchema: item.OutputSchema,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return web.JsonData(ret)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *MCPController) PostTest_connection() *web.JsonResult {
|
func (c *MCPController) PostTest_connection() *web.JsonResult {
|
||||||
if _, err := services.AuthService.RequirePermission(c.Ctx, constants.PermissionMCPView); err != nil {
|
if _, err := services.AuthService.RequirePermission(c.Ctx, constants.PermissionMCPView); err != nil {
|
||||||
return web.JsonError(err)
|
return web.JsonError(err)
|
||||||
|
|||||||
@@ -257,9 +257,15 @@ func validateSkillDefinitionRequest(req request.CreateSkillDefinitionRequest) er
|
|||||||
if _, err := normalizeJSONStringArray(req.Examples); err != nil {
|
if _, err := normalizeJSONStringArray(req.Examples); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := normalizeJSONStringArray(req.AllowedToolCodes); err != nil {
|
allowedToolCodes, err := normalizeJSONStringArray(req.AllowedToolCodes)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
for _, toolCode := range allowedToolCodes {
|
||||||
|
if err := services.ToolCatalogService.ValidateMCPToolCode(toolCode); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,16 @@ func BuildMCPToolInfoResponses(items []mcps.ToolInfo) []MCPToolInfoResponse {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MCPToolCatalogResponse struct {
|
||||||
|
ToolCode string `json:"toolCode"`
|
||||||
|
ServerCode string `json:"serverCode"`
|
||||||
|
ToolName string `json:"toolName"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
InputSchema any `json:"inputSchema"`
|
||||||
|
OutputSchema any `json:"outputSchema,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type MCPToolResultContentResponse struct {
|
type MCPToolResultContentResponse struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Text string `json:"text,omitempty"`
|
Text string `json:"text,omitempty"`
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"cs-agent/internal/ai/mcps"
|
||||||
|
"cs-agent/internal/pkg/config"
|
||||||
|
"cs-agent/internal/pkg/errorsx"
|
||||||
|
"cs-agent/internal/pkg/toolx"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ToolCatalogService = newToolCatalogService()
|
||||||
|
|
||||||
|
func newToolCatalogService() *toolCatalogService {
|
||||||
|
return &toolCatalogService{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type toolCatalogService struct{}
|
||||||
|
|
||||||
|
type MCPToolCatalogItem struct {
|
||||||
|
ToolCode string
|
||||||
|
ServerCode string
|
||||||
|
ToolName string
|
||||||
|
Title string
|
||||||
|
Description string
|
||||||
|
InputSchema any
|
||||||
|
OutputSchema any
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *toolCatalogService) ListMCPTools(ctx context.Context) ([]MCPToolCatalogItem, error) {
|
||||||
|
cfg := config.Current()
|
||||||
|
if !cfg.MCP.Enabled {
|
||||||
|
return nil, errorsx.InvalidParam("MCP未启用")
|
||||||
|
}
|
||||||
|
if len(cfg.MCP.Servers) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
serverCodes := make([]string, 0, len(cfg.MCP.Servers))
|
||||||
|
for serverCode, server := range cfg.MCP.Servers {
|
||||||
|
if !server.Enabled {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
serverCodes = append(serverCodes, serverCode)
|
||||||
|
}
|
||||||
|
slices.Sort(serverCodes)
|
||||||
|
ret := make([]MCPToolCatalogItem, 0)
|
||||||
|
for _, serverCode := range serverCodes {
|
||||||
|
tools, err := mcps.Runtime.ListTools(ctx, serverCode)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, item := range tools {
|
||||||
|
ret = append(ret, MCPToolCatalogItem{
|
||||||
|
ToolCode: toolx.BuildMCPToolCode(serverCode, item.Name),
|
||||||
|
ServerCode: serverCode,
|
||||||
|
ToolName: strings.TrimSpace(item.Name),
|
||||||
|
Title: strings.TrimSpace(item.Title),
|
||||||
|
Description: strings.TrimSpace(item.Description),
|
||||||
|
InputSchema: item.InputSchema,
|
||||||
|
OutputSchema: item.OutputSchema,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *toolCatalogService) ValidateMCPToolCode(toolCode string) error {
|
||||||
|
cfg := config.Current()
|
||||||
|
if !cfg.MCP.Enabled {
|
||||||
|
return errorsx.InvalidParam("MCP未启用")
|
||||||
|
}
|
||||||
|
serverCode, toolName := toolx.SplitMCPToolCode(toolCode)
|
||||||
|
if serverCode == "" || toolName == "" {
|
||||||
|
return errorsx.InvalidParam("toolCode格式不合法")
|
||||||
|
}
|
||||||
|
server, ok := cfg.MCP.Servers[serverCode]
|
||||||
|
if !ok || !server.Enabled {
|
||||||
|
return errorsx.InvalidParam("toolCode 绑定的 MCP 服务不存在或未启用")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user