Module: ModelContextProtocol::Server::Progressable
Instance Method Summary collapse
-
#progressable(max_duration:, message: nil) { ... } ⇒ Object
Execute a block with automatic time-based progress reporting.
Instance Method Details
#progressable(max_duration:, message: nil) { ... } ⇒ Object
Execute a block with automatic time-based progress reporting. Uses Concurrent::TimerTask to send progress notifications at regular intervals.
17 18 19 20 21 22 23 24 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 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 |
# File 'lib/model_context_protocol/server/progressable.rb', line 17 def progressable(max_duration:, message: nil, &block) context = Thread.current[:mcp_context] return yield unless context && context[:progress_token] && context[:transport] progress_token = context[:progress_token] transport = context[:transport] jsonrpc_request_id = context[:jsonrpc_request_id] request_store = context[:request_store] stream_id = context[:stream_id] start_time = Time.now update_interval = [1.0, max_duration * 0.05].max timer_task = Concurrent::TimerTask.new(execution_interval: update_interval) do Thread.current[:mcp_context] = {jsonrpc_request_id:} begin if request_store && jsonrpc_request_id break if request_store.cancelled?(jsonrpc_request_id) end elapsed_seconds = Time.now - start_time progress_pct = [(elapsed_seconds / max_duration) * 100, 99].min = if "#{} (#{elapsed_seconds.round(1)}s / ~#{max_duration}s)" else "Processing... (#{elapsed_seconds.round(1)}s / ~#{max_duration}s)" end begin transport.send_notification("notifications/progress", { progressToken: progress_token, progress: progress_pct.round(1), total: 100, message: }, session_id: stream_id) rescue break end timer_task.shutdown if elapsed_seconds >= max_duration ensure Thread.current[:mcp_context] = nil end end begin timer_task.execute result = yield original_context = Thread.current[:mcp_context] Thread.current[:mcp_context] = {jsonrpc_request_id:} begin transport.send_notification("notifications/progress", { progressToken: progress_token, progress: 100, total: 100, message: "Completed" }, session_id: stream_id) rescue nil ensure Thread.current[:mcp_context] = original_context end result ensure if timer_task&.running? timer_task.shutdown sleep(0.1) if timer_task.running? end end end |