toolsCallHandler generate a response for tools call.
(ctx context.Context, id jsonrpc.RequestId, toolset tools.Toolset, resourceMgr *resources.ResourceManager, body []byte, header http.Header)
| 200 | |
| 201 | // toolsCallHandler generate a response for tools call. |
| 202 | func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, toolset tools.Toolset, resourceMgr *resources.ResourceManager, body []byte, header http.Header) (any, error) { |
| 203 | authServices := resourceMgr.GetAuthServiceMap() |
| 204 | |
| 205 | // retrieve logger from context |
| 206 | logger, err := util.LoggerFromContext(ctx) |
| 207 | if err != nil { |
| 208 | return jsonrpc.NewError(id, jsonrpc.INTERNAL_ERROR, err.Error(), nil), err |
| 209 | } |
| 210 | |
| 211 | var req CallToolRequest |
| 212 | if err = json.Unmarshal(body, &req); err != nil { |
| 213 | err = fmt.Errorf("invalid mcp tools call request: %w", err) |
| 214 | return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err |
| 215 | } |
| 216 | validateHeaderErr, err := validateHeader(id, header, TOOLS_CALL, req.Params.Name) |
| 217 | if err != nil { |
| 218 | return validateHeaderErr, err |
| 219 | } |
| 220 | validateErr, err := validateMetadata(id, req.Params.RequestParams, header == nil) |
| 221 | if err != nil { |
| 222 | return validateErr, err |
| 223 | } |
| 224 | |
| 225 | toolName := req.Params.Name |
| 226 | toolArgument := req.Params.Arguments |
| 227 | logger.DebugContext(ctx, fmt.Sprintf("tool name: %s", toolName)) |
| 228 | |
| 229 | // Update span name and set gen_ai attributes |
| 230 | span := trace.SpanFromContext(ctx) |
| 231 | span.SetName(fmt.Sprintf("%s %s", TOOLS_CALL, toolName)) |
| 232 | span.SetAttributes( |
| 233 | attribute.String("gen_ai.tool.name", toolName), |
| 234 | attribute.String("gen_ai.operation.name", "execute_tool"), |
| 235 | ) |
| 236 | |
| 237 | // Verify tool belongs to the current toolset before resolving globally. |
| 238 | if !toolset.ContainsTool(toolName) { |
| 239 | err = fmt.Errorf("invalid tool name: tool with name %q does not exist", toolName) |
| 240 | return jsonrpc.NewError(id, jsonrpc.INVALID_PARAMS, err.Error(), nil), err |
| 241 | } |
| 242 | |
| 243 | tool, ok := resourceMgr.GetTool(toolName) |
| 244 | if !ok { |
| 245 | err = fmt.Errorf("invalid tool name: tool with name %q does not exist", toolName) |
| 246 | return jsonrpc.NewError(id, jsonrpc.INVALID_PARAMS, err.Error(), nil), err |
| 247 | } |
| 248 | |
| 249 | // Populate gen_ai attributes for operation duration metric |
| 250 | if genAIAttrs := util.GenAIMetricAttrsFromContext(ctx); genAIAttrs != nil { |
| 251 | genAIAttrs.OperationName = "execute_tool" |
| 252 | genAIAttrs.ToolName = toolName |
| 253 | } |
| 254 | |
| 255 | // Get access token |
| 256 | authTokenHeadername, err := tool.GetAuthTokenHeaderName(resourceMgr) |
| 257 | if err != nil { |
| 258 | errMsg := fmt.Errorf("error during invocation: %w", err) |
| 259 | return jsonrpc.NewError(id, jsonrpc.INTERNAL_ERROR, errMsg.Error(), nil), errMsg |