Progress

The MCP Ruby SDK supports progress tracking for long-running tool operations, following the MCP Progress specification.

How Progress Works

  1. Client Request: The client sends a progressToken in the _meta field when calling a tool
  2. Server Notification: The server sends notifications/progress messages back to the client during tool execution
  3. Tool Integration: Tools call server_context.report_progress to report incremental progress

Reporting Progress from Tools

Tools that accept a server_context: parameter can call report_progress on it. The server automatically wraps the context in an MCP::ServerContext instance that provides this method:

class LongRunningTool < MCP::Tool
  description "A tool that reports progress during execution"
  input_schema(
    properties: {
      count: { type: "integer" },
    },
    required: ["count"]
  )

  def self.call(count:, server_context:)
    count.times do |i|
      # Do work here.
      server_context.report_progress(i + 1, total: count, message: "Processing item #{i + 1}")
    end

    MCP::Tool::Response.new([{ type: "text", text: "Done" }])
  end
end

The server_context.report_progress method accepts:

  • progress (required) - current progress value (numeric)
  • total: (optional) - total expected value, so clients can display a percentage
  • message: (optional) - human-readable status message

report_progress is a no-op when the request carried no progressToken, and both numeric and string tokens are supported.

On the modern lifecycle, progress notifications emitted during a request ride the request’s own SSE response stream. The bundled transport buffers them and flushes after the handler returns, so they preserve order but arrive together with the final response rather than in real time.

Client Side

Requesting progress is the client’s side of the contract: pass progress_token: to MCP::Client#call_tool and the token is sent as _meta.progressToken, as shown on the client Transports page. The bundled client transports do not currently expose a callback for observing the incoming notifications/progress messages; the token’s effect is visible on the server side only.