feat(tools): 新增 4 个 agent 工具 —— web_search / web_fetch / calculator / current_datetime

均在 mcp-go,注册即 agent 可见(dispatcher 经 list_tools 动态发现,零改调度代码):

- web_search 联网搜索:Tavily(有 TAVILY_API_KEY 则用,干净 JSON)/ DuckDuckGo HTML(免 key 兜底)。
- web_fetch 网页抓取:取 URL → 去脚本样式 → 去标签 → 解实体 → 收敛空白,限 8000 rune;
  复用 external_api 的 SSRF 防护(拒环回/内网/元数据 + 重定向校验)。
- calculator 计算器:自研调度场算法求值(+ - * / % ^ 括号、一元负号),杜绝任意代码执行。
- current_datetime 当前时间:含星期与时区(可传 tz)。

测试:单测覆盖 evalArith(含右结合/一元负号/错误用例)、htmlToText(剔脚本样式+解实体)、
ddgUnwrap。live 自主 agent 实测:calculator (123+456)*7→4053、current_datetime 周三、
web_fetch example.com→200、web_search DDG 返回真实结果,全部端到端通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Blizzard
2026-06-24 16:47:15 +08:00
parent 700845d64a
commit e503965a83
3 changed files with 496 additions and 5 deletions
+32 -5
View File
@@ -81,7 +81,7 @@ func (g *Gateway) buildRegistry() map[string]toolDef {
// —— 暴露给自主 agent 的工具(带参数 schema / 注入声明)——
"wiki_search": {
cn: "知识检索", desc: "检索知识库,返回与查询最相关的资料片段。需要外部知识/事实依据时调用。",
agent: true,
agent: true,
params: []paramSpec{{Name: "q", Type: "string", Desc: "检索查询语句", Required: true}},
inject: []string{"kb"}, handler: g.wikiSearch,
},
@@ -102,6 +102,33 @@ func (g *Gateway) buildRegistry() map[string]toolDef {
cn: "历史召回", desc: "取当前会话最近多轮对话,用于理解上下文。",
agent: true, inject: []string{"session_id"}, handler: g.historyGet,
},
"web_search": {
cn: "联网搜索", desc: "联网搜索,返回最新网页结果(标题/链接/摘要)。需要实时/最新信息或外部事实时调用。",
agent: true,
params: []paramSpec{
{Name: "q", Type: "string", Desc: "搜索关键词", Required: true},
{Name: "topK", Type: "integer", Desc: "返回结果条数(默认 5,最多 10)"},
},
handler: g.webSearch,
},
"web_fetch": {
cn: "网页抓取", desc: "抓取一个网页 URL 并提取正文文本。需要读取某个链接的内容时调用。",
agent: true,
params: []paramSpec{{Name: "url", Type: "string", Desc: "要抓取的网页 URL", Required: true}},
handler: g.webFetch,
},
"calculator": {
cn: "计算器", desc: "精确计算数学表达式(+ - * / % ^ 与括号)。涉及算术/数值计算时调用,不要心算。",
agent: true,
params: []paramSpec{{Name: "expr", Type: "string", Desc: "数学表达式,如 (3+4)*2^3", Required: true}},
handler: g.calculator,
},
"current_datetime": {
cn: "当前时间", desc: "获取当前日期与时间(含星期)。需要“现在/今天几号/星期几”等时间信息时调用。",
agent: true,
params: []paramSpec{{Name: "tz", Type: "string", Desc: "可选时区,如 Asia/Shanghai;缺省服务器本地时区"}},
handler: g.currentDatetime,
},
// —— 仅内部/流水线/管理用,不暴露给自主 agent ——
"kb_ingest": {cn: "知识入库", desc: "文本切块 → 向量化 → 写入 Milvus / Bleve", handler: g.kbIngest},
@@ -147,10 +174,10 @@ func (g *Gateway) listTools() *contract.ToolResult {
Name string `json:"name"`
CN string `json:"cn"`
Desc string `json:"desc"`
Agent bool `json:"agent_exposed"` // 是否给自主 agent
AgentName string `json:"agent_name,omitempty"`// 模型可见名(空=name
Params []paramSpec `json:"params,omitempty"` // 模型可填参数
Inject []string `json:"inject,omitempty"` // 服务端注入参数(不暴露给模型)
Agent bool `json:"agent_exposed"` // 是否给自主 agent
AgentName string `json:"agent_name,omitempty"` // 模型可见名(空=name
Params []paramSpec `json:"params,omitempty"` // 模型可填参数
Inject []string `json:"inject,omitempty"` // 服务端注入参数(不暴露给模型)
}
out := make([]info, 0, len(g.tools))
for name, td := range g.tools {