Module: ActionMCP::Server::Tasks
- Included in:
- TransportHandler
- Defined in:
- lib/action_mcp/server/tasks.rb
Overview
Tasks module for MCP 2025-11-25 specification Provides methods for handling task-related requests:
- tasks/get: Get task status and data
- tasks/result: Get task result (blocking until a terminal state)
- tasks/list: List tasks for the session
- tasks/cancel: Cancel a task
Instance Method Summary collapse
-
#send_task_status_notification(task) ⇒ Object
Send task status notification.
-
#send_tasks_cancel(request_id, task_id) ⇒ Object
Cancel a task.
-
#send_tasks_get(request_id, task_id) ⇒ Object
Get task status and metadata.
-
#send_tasks_list(request_id, cursor: nil) ⇒ Object
List tasks for the session with keyset pagination.
-
#send_tasks_result(request_id, task_id) ⇒ Object
Get task result, blocking until the task reaches a terminal state.
Instance Method Details
#send_task_status_notification(task) ⇒ Object
Send task status notification
95 96 97 98 99 100 |
# File 'lib/action_mcp/server/tasks.rb', line 95 def send_task_status_notification(task) send_jsonrpc_notification( JsonRpcHandlerBase::Methods::NOTIFICATIONS_TASKS_STATUS, task.to_task_data ) end |
#send_tasks_cancel(request_id, task_id) ⇒ Object
Cancel a task
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 |
# File 'lib/action_mcp/server/tasks.rb', line 64 def send_tasks_cancel(request_id, task_id) task = find_task(task_id) return unless task terminal_status = nil task.with_lock do if task.terminal? terminal_status = task.status next end task. = "The task was cancelled by request." if task..blank? task.result_payload ||= { code: -32_000, message: "Task was cancelled" } task.save! if task.changed? task.cancel! end if terminal_status send_jsonrpc_error(request_id, :invalid_params, "Cannot cancel task in terminal status: #{terminal_status}") return end send_jsonrpc_response(request_id, result: task.to_task_data) end |
#send_tasks_get(request_id, task_id) ⇒ Object
Get task status and metadata
15 16 17 18 19 20 |
# File 'lib/action_mcp/server/tasks.rb', line 15 def send_tasks_get(request_id, task_id) task = find_task(task_id) return unless task send_jsonrpc_response(request_id, result: task.to_task_data) end |
#send_tasks_list(request_id, cursor: nil) ⇒ Object
List tasks for the session with keyset pagination. Tasks always paginate (AR-backed, can grow unbounded). Cursor is the last task id from the previous page. We resolve it through AR so the boundary matches the recent scope exactly.
50 51 52 53 54 55 56 57 58 59 |
# File 'lib/action_mcp/server/tasks.rb', line 50 def send_tasks_list(request_id, cursor: nil) page, next_cursor = paginate_tasks_by_recent(cursor: cursor, page_size: pagination_page_size || 50) result = { tasks: page.map(&:to_task_data) } result[:nextCursor] = next_cursor if next_cursor send_jsonrpc_response(request_id, result: result) rescue Server::CursorError => e send_jsonrpc_error(request_id, :invalid_params, e.) end |
#send_tasks_result(request_id, task_id) ⇒ Object
Get task result, blocking until the task reaches a terminal state.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/action_mcp/server/tasks.rb', line 25 def send_tasks_result(request_id, task_id) task = find_task(task_id) return unless task task = wait_for_terminal_task(task_id) unless task.terminal? unless task send_jsonrpc_error(request_id, :invalid_params, "Task '#{task_id}' not found") return end if (error = task.to_task_error) send_jsonrpc_response(request_id, error: error) else send_jsonrpc_response(request_id, result: task.to_task_result) end rescue ActiveRecord::RecordNotFound send_jsonrpc_error(request_id, :invalid_params, "Task '#{task_id}' not found") end |