feat(mcp-py,dispatcher): 自主 agent 工具动态发现覆盖 mcp-py
把动态工具发现从 mcp-go 扩到两台 MCP: - mcp-py:TOOL_META 改成与 mcp-go 同形(cn/desc/agent/params/inject), list_tools 上报这些;run_code 标 agent 可用(params: code)→ 自主 agent 可执行 Python 代码做计算/数据处理。 - dispatcher:agentTools 拆出 discoverTools(subject),分别探 mcp-go / mcp-py 的 list_tools 并合并;某台 MCP 离线即跳过(降级,不阻断)。 验收:mcp-py 未启动时自主 agent 仍正常(探测秒跳过),一次自主调用了 history_get + memory_get 两个动态发现的 go 工具(注入 session_id/user_id); go 全绿、mcp-py py_compile 通过。mcp-py 起着时 run_code 即自动入 agent 菜单。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -101,16 +101,26 @@ type toolCatalogEntry struct {
|
||||
Inject []string `json:"inject"`
|
||||
}
|
||||
|
||||
// agentTools 动态构建 ReAct 可用的工具集:调 MCP list_tools 自描述目录 → 取 agent_exposed 的工具
|
||||
// → 用上报的参数 schema 建 InvokableTool;inject 参数(user_id/session_id/kb/task_id)服务端运行时
|
||||
// 绑定、不暴露给模型。新增工具只需在 mcp-go 注册表标 agent,无需改这里(杜绝硬编码)。
|
||||
// agentTools 动态构建 ReAct 可用的工具集:分别向 mcp-go / mcp-py 探 list_tools 自描述目录,
|
||||
// 取 agent_exposed 的工具按上报参数 schema 建 InvokableTool;inject 参数(user_id/session_id/
|
||||
// kb/task_id)服务端运行时绑定、不暴露给模型。某台 MCP 离线即跳过(降级)。
|
||||
// 新增工具只需在对应 MCP 注册表标 agent,无需改这里(杜绝硬编码)。
|
||||
func (o *Orchestrator) agentTools(b *board, taskID string, tr *execTracer) []tool.BaseTool {
|
||||
if o.tools == nil {
|
||||
return nil
|
||||
}
|
||||
var out []tool.BaseTool
|
||||
out = append(out, o.discoverTools(contract.ToolSubjectGo, b, taskID, tr)...)
|
||||
out = append(out, o.discoverTools(contract.ToolSubjectPy, b, taskID, tr)...)
|
||||
return out
|
||||
}
|
||||
|
||||
// discoverTools 向某台 MCP(subject 前缀决定 go/py)探 list_tools,把 agent_exposed 的工具
|
||||
// 转成 Eino InvokableTool。该 MCP 不可用 / 无应答时返回空(不阻断)。
|
||||
func (o *Orchestrator) discoverTools(subject func(string) string, b *board, taskID string, tr *execTracer) []tool.BaseTool {
|
||||
cctx, cancel := context.WithTimeout(context.Background(), toolCallTimeout)
|
||||
defer cancel()
|
||||
res, err := o.tools.CallTool(cctx, contract.ToolSubjectGo("list_tools"), &contract.ToolCall{Tool: "list_tools"})
|
||||
res, err := o.tools.CallTool(cctx, subject("list_tools"), &contract.ToolCall{Tool: "list_tools"})
|
||||
if err != nil || res == nil || !res.OK {
|
||||
return nil
|
||||
}
|
||||
@@ -120,7 +130,6 @@ func (o *Orchestrator) agentTools(b *board, taskID string, tr *execTracer) []too
|
||||
if json.Unmarshal([]byte(res.Content), &cat) != nil {
|
||||
return nil
|
||||
}
|
||||
// inject 参数名 → 本任务的运行时值(不进模型菜单)。
|
||||
injectVal := map[string]any{"user_id": b.uid, "session_id": b.sid, "task_id": taskID, "kb": b.kb}
|
||||
|
||||
var out []tool.BaseTool
|
||||
@@ -144,7 +153,7 @@ func (o *Orchestrator) agentTools(b *board, taskID string, tr *execTracer) []too
|
||||
}
|
||||
out = append(out, &mcpTool{
|
||||
mcpName: e.Name,
|
||||
subject: contract.ToolSubjectGo,
|
||||
subject: subject,
|
||||
caller: o.tools, taskID: taskID, tr: tr,
|
||||
bind: bind,
|
||||
info: &schema.ToolInfo{
|
||||
|
||||
Reference in New Issue
Block a user