Module: ActionMCP::Server::Tools
- Included in:
- TransportHandler
- Defined in:
- lib/action_mcp/server/tools.rb
Instance Method Summary collapse
- #send_tools_call(request_id, tool_name, arguments, _meta = {}) ⇒ Object
- #send_tools_list(request_id, params = {}) ⇒ Object
Instance Method Details
#send_tools_call(request_id, tool_name, arguments, _meta = {}) ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/action_mcp/server/tools.rb', line 39 def send_tools_call(request_id, tool_name, arguments, = {}) # Find tool in session's registry tool_class = session.registered_tools.find { |t| t.tool_name == tool_name } unless tool_class Rails.logger.error "Tool not found: #{tool_name}. Registered tools: #{session.registered_tools.map(&:tool_name).join(', ')}" send_jsonrpc_error(request_id, :method_not_found, "Tool '#{tool_name}' not found or not registered for this session") return end # Check if tool requires consent and if consent is granted if tool_class.respond_to?(:requires_consent?) && tool_class. && !session.(tool_name) # Use custom error response for consent required (-32002) error = { code: -32_002, message: "Consent required for tool '#{tool_name}'" } send_jsonrpc_response(request_id, error: error) return end begin # Create tool and set execution context with request info tool = tool_class.new(arguments) tool.with_context({ session: session, request: { params: { name: tool_name, arguments: arguments, _meta: } } }) # Wrap tool execution with Rails reloader for development result = if Rails.env.development? # Preserve Current attributes across reloader boundary current_user = ActionMCP::Current.user current_gateway = ActionMCP::Current.gateway Rails.application.reloader.wrap do # Restore Current attributes inside reloader ActionMCP::Current.user = current_user ActionMCP::Current.gateway = current_gateway tool.call end else tool.call end if result.is_error # Protocol error send_jsonrpc_response(request_id, error: result.to_h) else # Success OR tool execution error - both are valid JSON-RPC responses send_jsonrpc_response(request_id, result: result.to_h) end rescue ArgumentError => e # Handle parameter validation errors send_jsonrpc_error(request_id, :invalid_params, e.) rescue StandardError => e # Log the actual error for debugging Rails.logger.error "Tool execution error: #{e.class} - #{e.message}" Rails.logger.error e.backtrace.join("\n") send_jsonrpc_error(request_id, :internal_error, "An unexpected error occurred.") end end |
#send_tools_list(request_id, params = {}) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/action_mcp/server/tools.rb', line 6 def send_tools_list(request_id, params = {}) protocol_version = session.protocol_version # Extract progress token from _meta if provided progress_token = params.dig("_meta", "progressToken") # Send initial progress notification if token is provided if progress_token send_progress_notification( progressToken: progress_token, progress: 0, message: "Starting tools list retrieval" ) end # Use session's registered tools instead of global registry registered_tools = session.registered_tools tools = registered_tools.map do |tool_class| tool_class.to_h(protocol_version: protocol_version) end # Send completion progress notification if token is provided if progress_token send_progress_notification( progressToken: progress_token, progress: 100, message: "Tools list retrieval complete" ) end send_jsonrpc_response(request_id, result: { tools: tools }) end |