---
layout: default
title: Progress
nav_order: 14
---

# Progress

The MCP Ruby SDK supports progress tracking for long-running tool operations,
following the [MCP Progress specification](https://modelcontextprotocol.io/specification/latest/server/utilities/progress).

## 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:`](/server/server-context/) parameter can call `report_progress` on it.
The server automatically wraps the context in an `MCP::ServerContext` instance that provides this method:

```ruby
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.

{: .note }
> On the [modern lifecycle](/server/discovery/#the-stateless-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](/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.
