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 terminal or input_required 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 task reaches terminal or input_required state.
Instance Method Details
#send_task_status_notification(task) ⇒ Object
Send task status notification
104 105 106 107 108 109 |
# File 'lib/action_mcp/server/tasks.rb', line 104 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
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/action_mcp/server/tasks.rb', line 82 def send_tasks_cancel(request_id, task_id) task = find_task(task_id) return unless task if task.terminal? send_jsonrpc_error(request_id, :invalid_params, "Cannot cancel task in terminal status: #{task.status}") return 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! 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.
68 69 70 71 72 73 74 75 76 77 |
# File 'lib/action_mcp/server/tasks.rb', line 68 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 task reaches terminal or input_required state
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# 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 unless task.result_ready? case ActionMCP.configuration.tasks_result_strategy when :polling_only send_jsonrpc_error( request_id, :invalid_request, "Task is not ready. Poll tasks/get over HTTP until the task reaches a terminal or input_required status, then retry tasks/result." ) return else task = wait_for_result_ready_task(task_id) unless task&.result_ready? send_jsonrpc_response( request_id, error: { code: -32_000, message: "Timed out waiting for task '#{task_id}' to reach a terminal or input_required status" } ) return end end 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 |