roots/list is a server → client request. GetMCP sends it down the outbound queue when a tool — or your own custom code — wants to know what local roots (directories, repositories) the user has exposed to the AI client.
The client responds with an array of { uri, name? } entries. The server caches that response per session and invalidates the cache when the client sends notifications/roots/list_changed.
When This Fires
GetMCP doesn’t fireroots/list automatically — there’s no “browse the user’s project” tool in the box. The handler is exposed so your own code (a custom tool, an action hook) can ask the question:
roots/list request; the result lands on the next inbound HTTP response from the client. Subsequent calls within the same session return the cached value until the client invalidates it.
Wire-level Shape
The server emits:Cache Invalidation
When the user changes their roots in the client UI, the client sends:request_for_session() call will issue a fresh roots/list.
Capability Negotiation
roots/list only works when the client declared the roots capability during initialize:
RootsHandler::request_for_session() returns an empty array immediately without queuing a request.
Roots are advisory. The client may decline to share them, return an empty list, or list paths that don’t exist. Always handle the empty case gracefully.

