feat: refactor MCP tool definitions to use a new tooling package and update related references

This commit is contained in:
mlogclub
2026-04-14 11:55:32 +08:00
parent 2cb4866fce
commit 9c7d70741a
12 changed files with 68 additions and 58 deletions
+6 -6
View File
@@ -4,8 +4,8 @@ import (
"encoding/json" "encoding/json"
"strings" "strings"
"cs-agent/internal/ai/runtime/internal/impl/adapter"
"cs-agent/internal/ai/runtime/registry" "cs-agent/internal/ai/runtime/registry"
runtimetooling "cs-agent/internal/ai/runtime/tooling"
"cs-agent/internal/models" "cs-agent/internal/models"
"cs-agent/internal/pkg/toolx" "cs-agent/internal/pkg/toolx"
@@ -13,7 +13,7 @@ import (
) )
type preparedTooling struct { type preparedTooling struct {
definitions []adapter.MCPToolDefinition definitions []runtimetooling.MCPToolDefinition
toolCodes []string toolCodes []string
toolDefsByModelName map[string]string toolDefsByModelName map[string]string
staticToolCodes []string staticToolCodes []string
@@ -22,7 +22,7 @@ type preparedTooling struct {
staticToolMetadata map[string]registry.ToolMetadata staticToolMetadata map[string]registry.ToolMetadata
} }
func prepareTooling(defs []adapter.MCPToolDefinition, selectedSkill *models.SkillDefinition, toolSet *registry.ToolSet, includeSkillTool bool) preparedTooling { func prepareTooling(defs []runtimetooling.MCPToolDefinition, selectedSkill *models.SkillDefinition, toolSet *registry.ToolSet, includeSkillTool bool) preparedTooling {
filteredDefs := filterToolDefinitionsBySkill(defs, selectedSkill) filteredDefs := filterToolDefinitionsBySkill(defs, selectedSkill)
ret := preparedTooling{ ret := preparedTooling{
definitions: filteredDefs, definitions: filteredDefs,
@@ -125,7 +125,7 @@ func staticToolCodeList(toolSet *registry.ToolSet) []string {
return ret return ret
} }
func definitionToolCodes(defs []adapter.MCPToolDefinition) []string { func definitionToolCodes(defs []runtimetooling.MCPToolDefinition) []string {
ret := make([]string, 0, len(defs)) ret := make([]string, 0, len(defs))
for _, item := range defs { for _, item := range defs {
code := strings.TrimSpace(item.ToolCode) code := strings.TrimSpace(item.ToolCode)
@@ -137,7 +137,7 @@ func definitionToolCodes(defs []adapter.MCPToolDefinition) []string {
return ret return ret
} }
func filterToolDefinitionsBySkill(defs []adapter.MCPToolDefinition, skill *models.SkillDefinition) []adapter.MCPToolDefinition { func filterToolDefinitionsBySkill(defs []runtimetooling.MCPToolDefinition, skill *models.SkillDefinition) []runtimetooling.MCPToolDefinition {
if skill == nil || strings.TrimSpace(skill.ToolWhitelist) == "" { if skill == nil || strings.TrimSpace(skill.ToolWhitelist) == "" {
return defs return defs
} }
@@ -156,7 +156,7 @@ func filterToolDefinitionsBySkill(defs []adapter.MCPToolDefinition, skill *model
if len(allowedSet) == 0 { if len(allowedSet) == 0 {
return defs return defs
} }
ret := make([]adapter.MCPToolDefinition, 0, len(defs)) ret := make([]runtimetooling.MCPToolDefinition, 0, len(defs))
for _, item := range defs { for _, item := range defs {
if _, ok := allowedSet[strings.TrimSpace(item.ToolCode)]; ok { if _, ok := allowedSet[strings.TrimSpace(item.ToolCode)]; ok {
ret = append(ret, item) ret = append(ret, item)
@@ -4,11 +4,10 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"hash/crc32"
"regexp"
"strings" "strings"
"cs-agent/internal/ai/mcps" "cs-agent/internal/ai/mcps"
runtimetooling "cs-agent/internal/ai/runtime/tooling"
einojsonschema "github.com/eino-contrib/jsonschema" einojsonschema "github.com/eino-contrib/jsonschema"
@@ -16,17 +15,7 @@ import (
"github.com/cloudwego/eino/schema" "github.com/cloudwego/eino/schema"
) )
var toolNameSanitizer = regexp.MustCompile(`[^a-zA-Z0-9_]`) type MCPToolDefinition = runtimetooling.MCPToolDefinition
type MCPToolDefinition struct {
ToolCode string
ServerCode string
ToolName string
ModelName string
Title string
Description string
FixedArgs map[string]string
}
type MCPTool struct { type MCPTool struct {
definition MCPToolDefinition definition MCPToolDefinition
@@ -83,7 +72,7 @@ func buildToolInfo(definition MCPToolDefinition, metadata *mcps.ToolInfo) *schem
desc = "Call MCP tool " + strings.TrimSpace(definition.ToolCode) desc = "Call MCP tool " + strings.TrimSpace(definition.ToolCode)
} }
info := &schema.ToolInfo{ info := &schema.ToolInfo{
Name: BuildModelToolName(definition), Name: runtimetooling.BuildModelToolName(definition),
Desc: desc, Desc: desc,
Extra: map[string]any{ Extra: map[string]any{
"toolCode": definition.ToolCode, "toolCode": definition.ToolCode,
@@ -145,17 +134,3 @@ func mergeFixedArguments(arguments map[string]any, fixedArgs map[string]string)
} }
return ret return ret
} }
func BuildModelToolName(definition MCPToolDefinition) string {
if strings.TrimSpace(definition.ModelName) != "" {
return strings.TrimSpace(definition.ModelName)
}
base := "mcp_" + strings.TrimSpace(definition.ServerCode) + "_" + strings.TrimSpace(definition.ToolName)
base = toolNameSanitizer.ReplaceAllString(base, "_")
base = strings.Trim(base, "_")
if base == "" {
base = "mcp_tool"
}
checksum := crc32.ChecksumIEEE([]byte(definition.ToolCode))
return fmt.Sprintf("%s_%08x", base, checksum)
}
@@ -4,10 +4,10 @@ import (
"context" "context"
"strings" "strings"
einoadapter "cs-agent/internal/ai/runtime/internal/impl/adapter"
einoagents "cs-agent/internal/ai/runtime/internal/impl/agents" einoagents "cs-agent/internal/ai/runtime/internal/impl/agents"
einocallbacks "cs-agent/internal/ai/runtime/internal/impl/callbacks" einocallbacks "cs-agent/internal/ai/runtime/internal/impl/callbacks"
"cs-agent/internal/ai/runtime/registry" "cs-agent/internal/ai/runtime/registry"
runtimetooling "cs-agent/internal/ai/runtime/tooling"
"cs-agent/internal/models" "cs-agent/internal/models"
"github.com/cloudwego/eino/adk" "github.com/cloudwego/eino/adk"
@@ -37,10 +37,10 @@ type BuildCustomerServiceAgentInput struct {
SelectedSkill *models.SkillDefinition SelectedSkill *models.SkillDefinition
// InstructionToolDefinitions 用于生成 instruction 中的工具说明。 // InstructionToolDefinitions 用于生成 instruction 中的工具说明。
// 它描述“当前允许模型理解和使用的 MCP 工具范围”。 // 它描述“当前允许模型理解和使用的 MCP 工具范围”。
InstructionToolDefinitions []einoadapter.MCPToolDefinition InstructionToolDefinitions []runtimetooling.MCPToolDefinition
// DynamicMCPToolDefinitions 用于接入 Eino tool_search middleware 的动态工具集合。 // DynamicMCPToolDefinitions 用于接入 Eino tool_search middleware 的动态工具集合。
// 这些工具默认不直接挂在 ToolsNode 上,而是经 tool_search 选择后再暴露给模型。 // 这些工具默认不直接挂在 ToolsNode 上,而是经 tool_search 选择后再暴露给模型。
DynamicMCPToolDefinitions []einoadapter.MCPToolDefinition DynamicMCPToolDefinitions []runtimetooling.MCPToolDefinition
// StaticTools 为当前运行时直接挂载到 ToolsNode 的固定工具,例如 Graph Tool。 // StaticTools 为当前运行时直接挂载到 ToolsNode 的固定工具,例如 Graph Tool。
StaticTools []einobasetool.BaseTool StaticTools []einobasetool.BaseTool
// StaticToolCodes 为固定工具的 modelName -> toolCode 映射,用于 trace 和运行日志归因。 // StaticToolCodes 为固定工具的 modelName -> toolCode 映射,用于 trace 和运行日志归因。
@@ -3,9 +3,9 @@ package factory
import ( import (
"context" "context"
einoadapter "cs-agent/internal/ai/runtime/internal/impl/adapter"
einocallbacks "cs-agent/internal/ai/runtime/internal/impl/callbacks" einocallbacks "cs-agent/internal/ai/runtime/internal/impl/callbacks"
"cs-agent/internal/ai/runtime/registry" "cs-agent/internal/ai/runtime/registry"
runtimetooling "cs-agent/internal/ai/runtime/tooling"
"cs-agent/internal/models" "cs-agent/internal/models"
"cs-agent/internal/pkg/toolx" "cs-agent/internal/pkg/toolx"
@@ -20,8 +20,8 @@ type AgentHandlerService struct {
type BuildAgentHandlersInput struct { type BuildAgentHandlersInput struct {
SelectedSkill *models.SkillDefinition SelectedSkill *models.SkillDefinition
InstructionToolDefinitions []einoadapter.MCPToolDefinition InstructionToolDefinitions []runtimetooling.MCPToolDefinition
DynamicToolDefinitions []einoadapter.MCPToolDefinition DynamicToolDefinitions []runtimetooling.MCPToolDefinition
DynamicTools []einobasetool.BaseTool DynamicTools []einobasetool.BaseTool
StaticToolMetadata map[string]registry.ToolMetadata StaticToolMetadata map[string]registry.ToolMetadata
Collector *einocallbacks.RuntimeTraceCollector Collector *einocallbacks.RuntimeTraceCollector
@@ -5,7 +5,7 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
einoadapter "cs-agent/internal/ai/runtime/internal/impl/adapter" runtimetooling "cs-agent/internal/ai/runtime/tooling"
"cs-agent/internal/models" "cs-agent/internal/models"
"cs-agent/internal/pkg/toolx" "cs-agent/internal/pkg/toolx"
) )
@@ -87,7 +87,7 @@ func (p *SkillInstructionProvider) Resolve(selectedSkill *models.SkillDefinition
return buildSelectedSkillActivationInstruction(selectedSkill) return buildSelectedSkillActivationInstruction(selectedSkill)
} }
func (p *ToolAppendixProvider) Build(toolDefinitions []einoadapter.MCPToolDefinition, extraToolCodes map[string]string) []string { func (p *ToolAppendixProvider) Build(toolDefinitions []runtimetooling.MCPToolDefinition, extraToolCodes map[string]string) []string {
appendixParts := make([]string, 0, 1) appendixParts := make([]string, 0, 1)
toolCodes := make([]string, 0, len(toolDefinitions)+len(extraToolCodes)) toolCodes := make([]string, 0, len(toolDefinitions)+len(extraToolCodes))
for _, item := range toolDefinitions { for _, item := range toolDefinitions {
@@ -3,7 +3,7 @@ package factory
import ( import (
"strings" "strings"
einoadapter "cs-agent/internal/ai/runtime/internal/impl/adapter" runtimetooling "cs-agent/internal/ai/runtime/tooling"
"cs-agent/internal/models" "cs-agent/internal/models"
) )
@@ -49,7 +49,7 @@ func NewInstructionService(
func (s *InstructionService) Build( func (s *InstructionService) Build(
aiAgent *models.AIAgent, aiAgent *models.AIAgent,
selectedSkill *models.SkillDefinition, selectedSkill *models.SkillDefinition,
toolDefinitions []einoadapter.MCPToolDefinition, toolDefinitions []runtimetooling.MCPToolDefinition,
extraToolCodes map[string]string, extraToolCodes map[string]string,
) InstructionAssemblyResult { ) InstructionAssemblyResult {
baseInstruction := "" baseInstruction := ""
@@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"strings" "strings"
einoadapter "cs-agent/internal/ai/runtime/internal/impl/adapter" runtimetooling "cs-agent/internal/ai/runtime/tooling"
"cs-agent/internal/models" "cs-agent/internal/models"
"cs-agent/internal/pkg/toolx" "cs-agent/internal/pkg/toolx"
) )
@@ -26,7 +26,7 @@ func buildSelectedSkillActivationInstruction(skill *models.SkillDefinition) stri
return strings.TrimSpace(strings.Join(lines, "\n")) return strings.TrimSpace(strings.Join(lines, "\n"))
} }
func buildSelectedSkillDocument(skill *models.SkillDefinition, toolDefinitions []einoadapter.MCPToolDefinition) string { func buildSelectedSkillDocument(skill *models.SkillDefinition, toolDefinitions []runtimetooling.MCPToolDefinition) string {
if skill == nil { if skill == nil {
return "" return ""
} }
@@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"strings" "strings"
einoadapter "cs-agent/internal/ai/runtime/internal/impl/adapter" runtimetooling "cs-agent/internal/ai/runtime/tooling"
"cs-agent/internal/models" "cs-agent/internal/models"
einoskill "github.com/cloudwego/eino/adk/middlewares/skill" einoskill "github.com/cloudwego/eino/adk/middlewares/skill"
@@ -16,7 +16,7 @@ type selectedSkillBackend struct {
skill einoskill.Skill skill einoskill.Skill
} }
func newSelectedSkillBackend(selectedSkill *models.SkillDefinition, toolDefinitions []einoadapter.MCPToolDefinition) (*selectedSkillBackend, error) { func newSelectedSkillBackend(selectedSkill *models.SkillDefinition, toolDefinitions []runtimetooling.MCPToolDefinition) (*selectedSkillBackend, error) {
if selectedSkill == nil { if selectedSkill == nil {
return nil, fmt.Errorf("selected skill is nil") return nil, fmt.Errorf("selected skill is nil")
} }
@@ -3,7 +3,7 @@ package factory
import ( import (
"context" "context"
einoadapter "cs-agent/internal/ai/runtime/internal/impl/adapter" runtimetooling "cs-agent/internal/ai/runtime/tooling"
"cs-agent/internal/models" "cs-agent/internal/models"
"cs-agent/internal/pkg/toolx" "cs-agent/internal/pkg/toolx"
@@ -20,7 +20,7 @@ func NewSkillMiddlewareService() *SkillMiddlewareService {
func (s *SkillMiddlewareService) Build( func (s *SkillMiddlewareService) Build(
ctx context.Context, ctx context.Context,
selectedSkill *models.SkillDefinition, selectedSkill *models.SkillDefinition,
toolDefinitions []einoadapter.MCPToolDefinition, toolDefinitions []runtimetooling.MCPToolDefinition,
) (adk.ChatModelAgentMiddleware, error) { ) (adk.ChatModelAgentMiddleware, error) {
backend, err := newSelectedSkillBackend(selectedSkill, toolDefinitions) backend, err := newSelectedSkillBackend(selectedSkill, toolDefinitions)
if err != nil { if err != nil {
@@ -6,6 +6,7 @@ import (
"cs-agent/internal/ai/mcps" "cs-agent/internal/ai/mcps"
impladapter "cs-agent/internal/ai/runtime/internal/impl/adapter" impladapter "cs-agent/internal/ai/runtime/internal/impl/adapter"
runtimetooling "cs-agent/internal/ai/runtime/tooling"
"cs-agent/internal/models" "cs-agent/internal/models"
"cs-agent/internal/pkg/toolx" "cs-agent/internal/pkg/toolx"
@@ -18,7 +19,7 @@ func NewToolFactory() *ToolFactory {
return &ToolFactory{} return &ToolFactory{}
} }
func (f *ToolFactory) BuildMCPTools(aiAgent *models.AIAgent) ([]impladapter.MCPToolDefinition, error) { func (f *ToolFactory) BuildMCPTools(aiAgent *models.AIAgent) ([]runtimetooling.MCPToolDefinition, error) {
if aiAgent == nil || strings.TrimSpace(aiAgent.AllowedMCPTools) == "" { if aiAgent == nil || strings.TrimSpace(aiAgent.AllowedMCPTools) == "" {
return nil, nil return nil, nil
} }
@@ -26,7 +27,7 @@ func (f *ToolFactory) BuildMCPTools(aiAgent *models.AIAgent) ([]impladapter.MCPT
if err != nil { if err != nil {
return nil, err return nil, err
} }
ret := make([]impladapter.MCPToolDefinition, 0, len(raw)) ret := make([]runtimetooling.MCPToolDefinition, 0, len(raw))
for _, item := range raw { for _, item := range raw {
toolCode := strings.TrimSpace(item.ToolCode) toolCode := strings.TrimSpace(item.ToolCode)
toolCode = toolx.NormalizeToolCodeAlias(toolCode) toolCode = toolx.NormalizeToolCodeAlias(toolCode)
@@ -37,7 +38,7 @@ func (f *ToolFactory) BuildMCPTools(aiAgent *models.AIAgent) ([]impladapter.MCPT
if serverCode == "" || toolName == "" { if serverCode == "" || toolName == "" {
continue continue
} }
definition := impladapter.MCPToolDefinition{ definition := runtimetooling.MCPToolDefinition{
ToolCode: toolCode, ToolCode: toolCode,
ServerCode: serverCode, ServerCode: serverCode,
ToolName: toolName, ToolName: toolName,
@@ -45,7 +46,7 @@ func (f *ToolFactory) BuildMCPTools(aiAgent *models.AIAgent) ([]impladapter.MCPT
Description: strings.TrimSpace(item.Description), Description: strings.TrimSpace(item.Description),
FixedArgs: cloneStringMap(item.Arguments), FixedArgs: cloneStringMap(item.Arguments),
} }
definition.ModelName = impladapter.BuildModelToolName(definition) definition.ModelName = runtimetooling.BuildModelToolName(definition)
ret = append(ret, definition) ret = append(ret, definition)
} }
return ret, nil return ret, nil
@@ -59,7 +60,7 @@ func (f *ToolFactory) BuildBaseTools(ctx context.Context, aiAgent *models.AIAgen
return f.BuildBaseToolsByDefinitions(ctx, definitions) return f.BuildBaseToolsByDefinitions(ctx, definitions)
} }
func (f *ToolFactory) BuildBaseToolsByDefinitions(ctx context.Context, definitions []impladapter.MCPToolDefinition) ([]einotool.BaseTool, error) { func (f *ToolFactory) BuildBaseToolsByDefinitions(ctx context.Context, definitions []runtimetooling.MCPToolDefinition) ([]einotool.BaseTool, error) {
if len(definitions) == 0 { if len(definitions) == 0 {
return nil, nil return nil, nil
} }
@@ -74,7 +75,7 @@ func (f *ToolFactory) BuildBaseToolsByDefinitions(ctx context.Context, definitio
return ret, nil return ret, nil
} }
func (f *ToolFactory) loadToolMetadata(ctx context.Context, definitions []impladapter.MCPToolDefinition) (map[string]*mcps.ToolInfo, error) { func (f *ToolFactory) loadToolMetadata(ctx context.Context, definitions []runtimetooling.MCPToolDefinition) (map[string]*mcps.ToolInfo, error) {
toolsByCode := make(map[string]*mcps.ToolInfo, len(definitions)) toolsByCode := make(map[string]*mcps.ToolInfo, len(definitions))
serverCodes := make(map[string]struct{}) serverCodes := make(map[string]struct{})
for _, item := range definitions { for _, item := range definitions {
@@ -3,9 +3,9 @@ package factory
import ( import (
"strings" "strings"
einoadapter "cs-agent/internal/ai/runtime/internal/impl/adapter"
einocallbacks "cs-agent/internal/ai/runtime/internal/impl/callbacks" einocallbacks "cs-agent/internal/ai/runtime/internal/impl/callbacks"
"cs-agent/internal/ai/runtime/registry" "cs-agent/internal/ai/runtime/registry"
runtimetooling "cs-agent/internal/ai/runtime/tooling"
"cs-agent/internal/models" "cs-agent/internal/models"
"cs-agent/internal/pkg/toolx" "cs-agent/internal/pkg/toolx"
) )
@@ -22,7 +22,7 @@ func buildInstructionTraceSummary(summary InstructionAssemblySummary) einocallba
} }
func buildRuntimeTraceToolMetadata( func buildRuntimeTraceToolMetadata(
dynamicToolDefinitions []einoadapter.MCPToolDefinition, dynamicToolDefinitions []runtimetooling.MCPToolDefinition,
staticToolMetadata map[string]registry.ToolMetadata, staticToolMetadata map[string]registry.ToolMetadata,
selectedSkill *models.SkillDefinition, selectedSkill *models.SkillDefinition,
) map[string]einocallbacks.ToolMetadata { ) map[string]einocallbacks.ToolMetadata {
@@ -0,0 +1,34 @@
package tooling
import (
"fmt"
"hash/crc32"
"regexp"
"strings"
)
var toolNameSanitizer = regexp.MustCompile(`[^a-zA-Z0-9_]`)
type MCPToolDefinition struct {
ToolCode string
ServerCode string
ToolName string
ModelName string
Title string
Description string
FixedArgs map[string]string
}
func BuildModelToolName(definition MCPToolDefinition) string {
if strings.TrimSpace(definition.ModelName) != "" {
return strings.TrimSpace(definition.ModelName)
}
base := "mcp_" + strings.TrimSpace(definition.ServerCode) + "_" + strings.TrimSpace(definition.ToolName)
base = toolNameSanitizer.ReplaceAllString(base, "_")
base = strings.Trim(base, "_")
if base == "" {
base = "mcp_tool"
}
checksum := crc32.ChecksumIEEE([]byte(definition.ToolCode))
return fmt.Sprintf("%s_%08x", base, checksum)
}