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()))
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -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"`
|
||||
|
||||
@@ -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