update
This commit is contained in:
+58
-11
@@ -44,7 +44,10 @@ end
|
||||
"""
|
||||
Extract text from MCP tool result content array.
|
||||
|
||||
Handles MCP's content format: [{"type":"text","text":"..."}]
|
||||
Handles JSON-RPC 2.0 result content format:
|
||||
{"content": [{"type": "text", "text": "..."}], "isError": false}
|
||||
|
||||
Returns the joined text content, or JSON-serialized fallback if no text blocks found.
|
||||
"""
|
||||
function _extract_text_content(result::Dict)::String
|
||||
content = get(result, "content", Any[])
|
||||
@@ -66,11 +69,12 @@ end
|
||||
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.
|
||||
method with the validated arguments. Responses are in JSON-RPC 2.0 format
|
||||
with result/error envelopes handled by the execute function.
|
||||
"""
|
||||
function _wrap_mcp_tool(mcpserver, tool_def::Dict{String,Any})::agentTool
|
||||
name = tool_def["toolName"]
|
||||
title = get(tool_def, "title", name)
|
||||
name = tool_def["name"]
|
||||
title = get(tool_def, "title", get(tool_def, "label", name))
|
||||
desc = get(tool_def, "description", "")
|
||||
input_schema = get(tool_def, "inputSchema", Dict{String,Any}())
|
||||
|
||||
@@ -101,6 +105,17 @@ function _wrap_mcp_tool(mcpserver, tool_def::Dict{String,Any})::agentTool
|
||||
try
|
||||
response = mcpserver("tools/call", name, args)
|
||||
|
||||
# Parse JSON-RPC 2.0 response envelope
|
||||
if haskey(response, "error")
|
||||
rpc_error = response["error"]
|
||||
err_msg = get(rpc_error, "message", "Unknown MCP error")
|
||||
return agentToolResult(
|
||||
[textContent("MCP error: $err_msg")],
|
||||
Dict{Any,Any}("error" => err_msg),
|
||||
nothing, false
|
||||
)
|
||||
end
|
||||
|
||||
result_data = get(response, "result", response)
|
||||
content_text = _extract_text_content(result_data)
|
||||
is_error = get(result_data, "isError", false)
|
||||
@@ -128,9 +143,10 @@ end
|
||||
"""
|
||||
Discover and register MCP tools into `store.tools`.
|
||||
|
||||
Queries the MCP server via `mcpserver("tools/list")`, parses the response,
|
||||
and registers each discovered tool. Skips tools already registered.
|
||||
Returns `(new_count, tool_list_text)`.
|
||||
Queries the MCP server via `mcpserver("tools/list")` (JSON-RPC 2.0 format),
|
||||
parses the response envelope, and registers each discovered tool.
|
||||
Handles pagination via `nextCursor` — keeps fetching until cursor is empty.
|
||||
Skips tools already registered. Returns `(new_count, tool_list_text)`.
|
||||
"""
|
||||
function _register_mcp_tools(mcpserver, store::toolStore)::Tuple{Int, String}
|
||||
if mcpserver === nothing
|
||||
@@ -139,11 +155,23 @@ function _register_mcp_tools(mcpserver, store::toolStore)::Tuple{Int, String}
|
||||
|
||||
try
|
||||
response = mcpserver("tools/list")
|
||||
|
||||
# Parse JSON-RPC 2.0 response envelope
|
||||
if haskey(response, "error")
|
||||
rpc_error = response["error"]
|
||||
err_msg = get(rpc_error, "message", "Unknown MCP error")
|
||||
return (0, "MCP tools/list failed: $err_msg")
|
||||
end
|
||||
if haskey(response, "result")
|
||||
response = response["result"]
|
||||
end
|
||||
|
||||
tools_array = response["tools"]
|
||||
cursor = get(response, "nextCursor", nothing)
|
||||
|
||||
new_count = 0
|
||||
for tool_def in tools_array
|
||||
name = tool_def["toolName"]
|
||||
name = tool_def["name"]
|
||||
if haskey(store.tools, name)
|
||||
continue
|
||||
end
|
||||
@@ -152,6 +180,25 @@ function _register_mcp_tools(mcpserver, store::toolStore)::Tuple{Int, String}
|
||||
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(store.tools, name)
|
||||
continue
|
||||
end
|
||||
wrapped = _wrap_mcp_tool(mcpserver, tool_def)
|
||||
store.tools[name] = wrapped
|
||||
new_count += 1
|
||||
end
|
||||
end
|
||||
|
||||
# Build readable tool list
|
||||
lines = String[
|
||||
"- $(t.name): $(t.label) — $(t.description)"
|
||||
@@ -169,11 +216,11 @@ end
|
||||
"""
|
||||
listTool(store::toolStore, mcpserver) -> agentTool
|
||||
|
||||
MCP-aware listTools tool.
|
||||
MCP-aware listTools tool (JSON-RPC 2.0 protocol).
|
||||
|
||||
First call: queries the MCP server via `mcpserver("tools/list")`, registers
|
||||
all discovered tools into the shared `store.tools` (in-place mutation),
|
||||
then returns the full tool list.
|
||||
all discovered tools into the shared `store.tools` (in-place mutation, with
|
||||
pagination via nextCursor), then returns the full tool list.
|
||||
|
||||
Subsequent calls: returns the current list (tools remain registered).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user