[DOCS] MCP `roots/list` reference and `list_changed` section do not describe the v2.1.203 client-side update that exposes additional working directories and emits `notifications/roots/list_changed`

Open 💬 0 comments Opened Jul 7, 2026 by coygeek

Documentation Type

Incorrect/outdated documentation

Documentation Location

https://code.claude.com/docs/en/mcp

Section/Topic

The two places on the MCP reference page that talk about roots:

  • The stdio-server paragraph under "Option 3: Add a local stdio server" that introduces CLAUDE_PROJECT_DIR and ends with the sentence about calling the MCP roots/list request.
  • The "Dynamic tool updates" subsection that explains MCP list_changed notifications.

The same roots/list sentence is repeated in the plugins reference (plugins-reference.md, under the environment-variable table where ${CLAUDE_PROJECT_DIR} is documented).

Current Documentation

From mcp.md, the stdio-server paragraph around the CLAUDE_PROJECT_DIR description:

"Claude Code sets CLAUDE_PROJECT_DIR in the spawned server's environment to the project root, so your server can resolve project-relative paths without depending on the working directory. This is the same directory hooks receive in their CLAUDE_PROJECT_DIR variable. Read it from inside your server process, for example process.env.CLAUDE_PROJECT_DIR in Node or os.environ["CLAUDE_PROJECT_DIR"] in Python." "Your server can also call the MCP roots/list request, which returns the directory Claude Code was launched from."

From mcp.md, the "Dynamic tool updates" section:

"Claude Code supports MCP list_changed notifications, allowing MCP servers to dynamically update their available tools, prompts, and resources without requiring you to disconnect and reconnect. When an MCP server sends a list_changed notification, Claude Code automatically refreshes the available capabilities from that server."

From plugins-reference.md, the ${CLAUDE_PROJECT_DIR} row:

"${CLAUDE_PROJECT_DIR}: the project root. This is the same directory hooks receive in their CLAUDE_PROJECT_DIR variable. Use this to reference project-local scripts or config files. Wrap in quotes to handle paths with spaces, for example "${CLAUDE_PROJECT_DIR}/scripts/server.sh". MCP servers can also call the MCP roots/list request, which returns the directory Claude Code was launched from."

What's Wrong or Missing?

A. The roots/list description is incomplete after v2.1.203

The v2.1.203 changelog entry reads:

"Added the session's additional working directories to MCP roots/list, with notifications/roots/list_changed sent when the set changes"

Before v2.1.203, roots/list returned only the directory Claude Code was launched from (the project root). After v2.1.203 it also returns every additional working directory the session has open — that is, the union of the launch directory and every directory added with --add-dir, /add-dir, or permissions.additionalDirectories in settings. The stdio-server paragraph still describes only the launch-directory case, so a server author reading it today will write code that calls roots/list once at startup and assumes the result never grows. With v2.1.203 the result can grow during the session, and servers that only read roots once will silently miss the added directories.

B. The "Dynamic tool updates" section never mentions notifications/roots/list_changed

The "Dynamic tool updates" heading frames list_changed as something servers send to Claude Code. After v2.1.203 the flow also runs in the opposite direction: Claude Code sends notifications/roots/list_changed to MCP servers whenever the set of additional working directories changes (for example after a successful /add-dir, a settings update that adds or removes an entry, or a --resume that carries the directory state of the previous session). The current page does not describe this client-side notification at all, and the existing prose — "When an MCP server sends a list_changed notification, Claude Code automatically refreshes the available capabilities from that server" — gives a server implementer no reason to subscribe to the roots variant.

C. The plugins-reference paraphrase repeats the same incomplete sentence

plugins-reference.md quotes the same roots/list description in its ${CLAUDE_PROJECT_DIR} row. The wording "the directory Claude Code was launched from" is no longer accurate after v2.1.203, so the plugins reference inherits the same gap.

Suggested Improvement

Update the stdio-server paragraph in mcp.md to describe the full root set:

"Your server can also call the MCP roots/list request, which returns the directory Claude Code was launched from together with every additional working directory the session has open — the directories added with --add-dir, /add-dir, or permissions.additionalDirectories in settings."

Add a separate paragraph or subsection describing the client-side list_changed notification:

"Claude Code also sends notifications/roots/list_changed to MCP servers whenever the set of additional working directories changes during the session — for example after /add-dir, after permissions.additionalDirectories is updated, or on --resume when a previous session's directory state carries over. Re-call roots/list after receiving this notification to pick up the new set. Subscribe to it from your server's initialization handler so the directory set stays current for path-scoped tool behavior."

Update the "Dynamic tool updates" heading and lead-in to cover both directions, for example:

"### Dynamic tool updates Claude Code supports MCP list_changed notifications in both directions: Servers → Claude Code: when an MCP server sends a list_changed notification, Claude Code automatically refreshes the available tools, prompts, and resources from that server. Claude Code → servers: when the set of additional working directories changes during a session, Claude Code sends notifications/roots/list_changed. Servers should re-call roots/list to pick up the new set."

Mirror the roots/list clarification in plugins-reference.md so the ${CLAUDE_PROJECT_DIR} row no longer claims the launch directory is the only root:

"MCP servers can also call the MCP roots/list request, which returns the directory Claude Code was launched from plus every additional working directory the session has open."

Impact

Medium - Makes feature difficult to understand

Additional Context

Affected Pages:
| Page | Line(s) | Context |
|------|---------|---------|
| https://code.claude.com/docs/en/mcp | 106 | roots/list described as returning only the launch directory |
| https://code.claude.com/docs/en/mcp | 184–186 | "Dynamic tool updates" section only covers server → client list_changed |
| https://code.claude.com/docs/en/plugins-reference | 643 | ${CLAUDE_PROJECT_DIR} row repeats the incomplete roots/list description |

Total scope: 2 pages affected.

Version: Introduced in v2.1.203. The change is also client-visible on --resume of a session that previously had additional directories added, since the directory set carries over from the previous session.

Cross-references:

View original on GitHub ↗