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:
mlogclub
2026-04-09 15:24:34 +08:00
parent dbd1c5fe66
commit 92490d7faf
4 changed files with 123 additions and 1 deletions
@@ -24,6 +24,29 @@ func (c *MCPController) AnyList_servers() *web.JsonResult {
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 {
if _, err := services.AuthService.RequirePermission(c.Ctx, constants.PermissionMCPView); err != nil {
return web.JsonError(err)
@@ -257,9 +257,15 @@ func validateSkillDefinitionRequest(req request.CreateSkillDefinitionRequest) er
if _, err := normalizeJSONStringArray(req.Examples); err != nil {
return err
}
if _, err := normalizeJSONStringArray(req.AllowedToolCodes); err != nil {
allowedToolCodes, err := normalizeJSONStringArray(req.AllowedToolCodes)
if err != nil {
return err
}
for _, toolCode := range allowedToolCodes {
if err := services.ToolCatalogService.ValidateMCPToolCode(toolCode); err != nil {
return err
}
}
return nil
}
+10
View File
@@ -65,6 +65,16 @@ func BuildMCPToolInfoResponses(items []mcps.ToolInfo) []MCPToolInfoResponse {
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 string `json:"type"`
Text string `json:"text,omitempty"`
+83
View File
@@ -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
}