Three pages carried names the 2026-07-28 specification does not use: "Multi-Round-Trip Results" for the pattern the specification titles Multi Round-Trip Requests (MRTR) and serves at basic/patterns/mrtr - the results are the `InputRequiredResult` wire type, not the feature - plus "Completions" for the utility the specification titles Completion, and "Notification Subscriptions" for the pattern it titles Subscriptions. Retitle the three pages to the specification's names, move them to /server/mrtr/ and /client/mrtr/, /server/completion/, and /server/subscriptions/ following the specification's slugs, update every internal reference, and keep the URLs published with v1.3.0 working via jekyll-redirect-from. The Discovery page keeps its title but moves from /server/discovery/ to /server/discover/, matching the specification's slug and the `server/discover` RPC, with its published URL redirected the same way.
64 lines
2.4 KiB
Markdown
64 lines
2.4 KiB
Markdown
---
|
|
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/discover/#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.
|