This commit is contained in:
2026-08-24 13:33:20 +07:00
parent 5f284883b3
commit 9193260539
4 changed files with 58 additions and 117 deletions
+55 -57
View File
@@ -38,7 +38,7 @@ Wrap an MCP tool definition as an `agentTool`.
The returned tool's `execute` function calls the MCP server's "tools/call"
method with the validated arguments.
"""
function _wrap_mcp_tool(mcpserver, tool_def::AbstractDict{String, Any}; eventSink=nothing)::agentTool
function _wrap_mcp_tool(mcpserver, tool_def::AbstractDict{String, Any}; eventSink=nothing, sessionId=nothing)::agentTool
name = tool_def["name"]
title = get(tool_def, "title", get(tool_def, "label", name))
desc = get(tool_def, "description", "")
@@ -68,7 +68,7 @@ function _wrap_mcp_tool(mcpserver, tool_def::AbstractDict{String, Any}; eventSin
signal::Union{Nothing,abortSignal},
eventSink) -> begin
try
response = mcpserver("tools/call", name, args)
response = mcpserver("tools/call", name, args, sessionId)
# Parse JSON-RPC 2.0 response envelope
if haskey(response, "error")
@@ -115,76 +115,74 @@ Handles pagination via `nextCursor`. Skips tools already registered.
# Returns
- `Int`: number of new tools registered
"""
function register_mcp_tools(tools::OrderedDict{String, agentTool}, mcpserver; eventSink=nothing)::Int
if mcpserver === nothing
function register_mcp_tools(tools::OrderedDict{String, agentTool}, mcpserver; eventSink=nothing, sessionId=nothing)::Int
if mcpserver === nothing
return 0
end
new_count = 0
try
eventSink("register_mcp_tools 1")
response = mcpserver("tools/list", sessionId)
eventSink("register_mcp_tools 2")
# Parse JSON-RPC 2.0 response envelope
if haskey(response, "error")
rpc_error = response["error"]
err_msg = get(rpc_error, "message", "Unknown MCP error")
println("[toolRegistry] MCP tools/list failed: $err_msg")
return 0
end
if haskey(response, "result")
response = response["result"]
end
new_count = 0
tools_array = response["tools"]
cursor = get(response, "nextCursor", nothing)
try
eventSink("register_mcp_tools 1")
response = mcpserver("tools/list")
eventSink("register_mcp_tools 2")
# Parse JSON-RPC 2.0 response envelope
if haskey(response, "error")
rpc_error = response["error"]
err_msg = get(rpc_error, "message", "Unknown MCP error")
println("[toolRegistry] MCP tools/list failed: $err_msg")
return 0
for tool_def in tools_array
name = tool_def["name"]
if haskey(tools, name)
continue
end
wrapped = _wrap_mcp_tool(mcpserver, tool_def, eventSink=eventSink, sessionId=sessionId)
tools[name] = wrapped
new_count += 1
end
# Paginate: fetch remaining tools if nextCursor is present
while cursor !== nothing && cursor !== ""
response = sessionId !== nothing ? mcpserver("tools/list", sessionId) : mcpserver("tools/list")
if haskey(response, "result")
response = response["result"]
end
tools_array = response["tools"]
tools_array = get(response, "tools", Any[])
cursor = get(response, "nextCursor", nothing)
for tool_def in tools_array
name = tool_def["name"]
if haskey(tools, name)
continue
end
wrapped = _wrap_mcp_tool(mcpserver, tool_def, eventSink=eventSink)
wrapped = _wrap_mcp_tool(mcpserver, tool_def, eventSink=eventSink, sessionId=sessionId)
tools[name] = wrapped
new_count += 1
end
# Paginate: fetch remaining tools if nextCursor is present
while cursor !== nothing && cursor !== ""
response = mcpserver("tools/list")
if haskey(response, "result")
response = response["result"]
end
tools_array = get(response, "tools", Any[])
cursor = get(response, "nextCursor", nothing)
for tool_def in tools_array
name = tool_def["name"]
if haskey(tools, name)
continue
end
wrapped = _wrap_mcp_tool(mcpserver, tool_def, eventSink=eventSink)
tools[name] = wrapped
new_count += 1
end
end
println("[toolRegistry] Discovered $new_count MCP tools. Total: $(length(tools))")
catch e
bt = catch_backtrace()
err_msg = sprint() do io
showerror(io, e, bt)
println(io)
end
eventSink(err_msg)
errMsg = sprint(showerror, e)
println("[toolRegistry] MCP tools/list failed: $errMsg")
end
return new_count
println("[toolRegistry] Discovered $new_count MCP tools. Total: $(length(tools))")
catch e
bt = catch_backtrace()
err_msg = sprint() do io
showerror(io, e, bt)
println(io)
end
eventSink(err_msg)
errMsg = sprint(showerror, e)
println("[toolRegistry] MCP tools/list failed: $errMsg")
end
return new_count
end
"""
@@ -234,7 +232,7 @@ pagination via nextCursor), then returns the full tool list.
Subsequent calls: returns the current list (tools remain registered).
"""
function listTool(tools::OrderedDict{String, agentTool}, mcpserver; eventSink=nothing)::agentTool
function listTool(tools::OrderedDict{String, agentTool}, mcpserver; eventSink=nothing, sessionId=nothing)::agentTool
return agentTool(
name="listTools",
label="List Tools",
@@ -248,7 +246,7 @@ function listTool(tools::OrderedDict{String, agentTool}, mcpserver; eventSink=no
signal::Union{Nothing,abortSignal},
eventSink) -> begin
# Discover and register MCP tools (idempotent — skips already registered)
new_count = register_mcp_tools(tools, mcpserver; eventSink=eventSink)
new_count = register_mcp_tools(tools, mcpserver; eventSink=eventSink, sessionId=sessionId)
eventSink("tools dump: " * sprint(show, tools))
# Always include listTools itself in the count
@@ -285,8 +283,8 @@ Register all tools for an agent:
- `tools`: The tool dict to populate
- `mcpserver`: A callable struct that communicates with the MCP server
"""
function registerAllTools(tools::OrderedDict{String, agentTool}, mcpserver=nothing; eventSink=nothing)
list_t = listTool(tools, mcpserver; eventSink=eventSink)
function registerAllTools(tools::OrderedDict{String, agentTool}, mcpserver=nothing; eventSink=nothing, sessionId=nothing)
list_t = listTool(tools, mcpserver; eventSink=eventSink, sessionId=sessionId)
registerTool(tools, list_t; eventSink=eventSink)
end