feat(clawhubadapter): rename plugin tools, universal uninstall; feat(mcp): add dynamic server management; feat(prompt): long-task guidance

This commit is contained in:
root
2026-07-22 17:32:45 +08:00
parent bd0f84c1f7
commit 9b4d0cb50d
3 changed files with 217 additions and 19 deletions

View File

@ -79,6 +79,47 @@ func (p *Plugin) Start(s *sdk.PluginSDK) error {
log.Printf("[mcp] register restart tool: %v", err)
}
// MCP 服务器动态管理工具
addDef := sdk.ToolDef{
Name: "mcp_add_server",
Description: "动态添加并连接一个新的 MCP 服务器。支持 stdio 模式(指定 command和 SSE 模式(指定 url。添加后该服务器的所有工具立即可用。",
Parameters: map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"name": map[string]interface{}{"type": "string", "description": "服务器名称(唯一标识,如 my-service"},
"command": map[string]interface{}{"type": "string", "description": "stdio 模式:可执行文件路径(如 npx"},
"args": map[string]interface{}{"type": "string", "description": "命令行参数JSON 字符串数组(如 [\"-y\", \"@modelcontextprotocol/server-everything\"]"},
"url": map[string]interface{}{"type": "string", "description": "SSE 模式:服务器 URL如 https://api.example.com/mcp"},
"env": map[string]interface{}{"type": "string", "description": "环境变量JSON 字符串对象(如 {\"KEY\": \"value\"}"},
},
"required": []string{"name"},
},
}
s.RegisterTool("mcp_add_server", addDef, p.addServerHandler)
removeDef := sdk.ToolDef{
Name: "mcp_remove_server",
Description: "断开并移除一个已连接的 MCP 服务器。会关闭连接并清理注册的工具(部分清理在重启后完全生效)。",
Parameters: map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"name": map[string]interface{}{"type": "string", "description": "要移除的 MCP 服务器名称"},
},
"required": []string{"name"},
},
}
s.RegisterTool("mcp_remove_server", removeDef, p.removeServerHandler)
listDef := sdk.ToolDef{
Name: "mcp_list_servers",
Description: "列出所有已连接的 MCP 服务器及其工具。",
Parameters: map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{},
},
}
s.RegisterTool("mcp_list_servers", listDef, p.listServersHandler)
return nil
}
@ -253,6 +294,123 @@ func (p *Plugin) restartServerHandler(args map[string]interface{}) (interface{},
return fmt.Sprintf("MCP 服务器 [%s] 已成功重启", name), nil
}
func (p *Plugin) addServerHandler(args map[string]interface{}) (interface{}, error) {
name, _ := args["name"].(string)
if name == "" {
return "参数 name 不能为空", nil
}
cfg := serverConfig{Name: name}
if v, _ := args["command"].(string); v != "" {
cfg.Command = v
}
if v, _ := args["url"].(string); v != "" {
cfg.URL = v
}
if v, _ := args["args"].(string); v != "" {
json.Unmarshal([]byte(v), &cfg.Args)
}
if v, _ := args["env"].(string); v != "" {
// 支持 JSON 对象和 JSON 字符串数组两种格式
var envObj map[string]string
if err := json.Unmarshal([]byte(v), &envObj); err == nil {
for k, val := range envObj {
cfg.Env = append(cfg.Env, k+"="+val)
}
} else {
json.Unmarshal([]byte(v), &cfg.Env)
}
}
if cfg.Command == "" && cfg.URL == "" {
return "必须指定 commandstdio 模式)或 urlSSE 模式)", nil
}
// 检查是否已存在同名服务器
p.mu.Lock()
for _, s := range p.servers {
if s.Name() == name {
p.mu.Unlock()
return fmt.Sprintf("MCP 服务器 [%s] 已存在。如要重启请使用 mcp_restart_server如要替换请先 mcp_remove_server", name), nil
}
}
p.mu.Unlock()
if err := p.connectAndRegister(cfg); err != nil {
return fmt.Sprintf("连接 MCP 服务器 [%s] 失败: %v", name, err), nil
}
p.mu.Lock()
p.configs = append(p.configs, cfg)
p.mu.Unlock()
return fmt.Sprintf("MCP 服务器 [%s] 已成功连接并注册所有工具", name), nil
}
func (p *Plugin) removeServerHandler(args map[string]interface{}) (interface{}, error) {
name, _ := args["name"].(string)
if name == "" {
return "参数 name 不能为空", nil
}
p.mu.Lock()
var keptServers []*Server
var removed bool
for _, s := range p.servers {
if s.Name() == name {
s.Close()
removed = true
} else {
keptServers = append(keptServers, s)
}
}
p.servers = keptServers
var keptConfigs []serverConfig
for _, c := range p.configs {
if c.Name != name {
keptConfigs = append(keptConfigs, c)
}
}
p.configs = keptConfigs
p.mu.Unlock()
if !removed {
return fmt.Sprintf("MCP 服务器 [%s] 不存在", name), nil
}
return fmt.Sprintf("MCP 服务器 [%s] 已断开连接。工具注册信息将在重启后完全清理。", name), nil
}
func (p *Plugin) listServersHandler(args map[string]interface{}) (interface{}, error) {
p.mu.Lock()
defer p.mu.Unlock()
if len(p.servers) == 0 {
return "没有已连接的 MCP 服务器。", nil
}
var lines []string
lines = append(lines, fmt.Sprintf("已连接的 MCP 服务器 (%d):", len(p.servers)))
for _, s := range p.servers {
tools, err := s.ListTools()
var toolInfo string
if err == nil && len(tools) > 0 {
var names []string
for _, t := range tools {
names = append(names, t.Name)
}
toolInfo = strings.Join(names, ", ")
} else if err != nil {
toolInfo = fmt.Sprintf("(查询工具失败: %v)", err)
} else {
toolInfo = "(无工具)"
}
lines = append(lines, fmt.Sprintf(" %s: %s", s.Name(), toolInfo))
}
return strings.Join(lines, "\n"), nil
}
func newTransport(cfg serverConfig) (Transport, error) {
if cfg.URL != "" {
return NewSSETransport(cfg.URL), nil