Skip to main content
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 fire roots/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:
The first call queues a 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:
The client responds (on its next outbound request):

Cache Invalidation

When the user changes their roots in the client UI, the client sends:
GetMCP drops its cached copy and the next 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:
If the capability is absent, 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.