MCP Roots let clients tell the server which filesystem areas are in scope. mcp-bash uses the standard roots/list flow and exposes the resulting roots to tools.
- During
initialize, the lifecycle handler records whether the client advertisesrootsandroots.listChanged. - After
initialized, the server sendsroots/listto the client. Responses are matched via the RPC callback registry. - If a client emits
notifications/roots/list_changed, the server re-requests roots (debounced). - While a refresh is in flight, the cached roots remain available; client responses replace the cache on success.
- Timeouts or client errors keep the existing roots (no noisy warnings); malformed client payloads are ignored.
Every tool receives these env vars (populated once roots are ready):
MCP_ROOTS_JSON– JSON array of roots withuri,name, and normalizedpath.MCP_ROOTS_PATHS– newline-separated list of normalized absolute paths.MCP_ROOTS_COUNT– number of roots.
SDK helpers in sdk/tool-sdk.sh:
mcp_roots_list– printsMCP_ROOTS_PATHS.mcp_roots_count– prints the count.mcp_roots_contains <path>– returns 0 if the path is within any root.
Priority (highest to lowest):
--rootsflag tomcp-bash run-tool(run-tool only; comma-separated)MCPBASH_ROOTS=/path/one:/path/two(colon-separated; absolute or relative toMCPBASH_PROJECT_ROOT)config/roots.jsonin your project:{ "roots": [ { "path": "./data", "name": "Data" }, { "path": "/shared/media", "name": "Media" } ] }- Default:
MCPBASH_PROJECT_ROOT(implicit single root)
Behavior:
--roots/MCPBASH_ROOTSfail fast on invalid paths (non-existent or unreadable).config/roots.jsonwarns and skips invalid entries but keeps valid ones.- Client roots replace the current cache on success; malformed client payloads keep the previous roots.
- Run
./examples/run 04-roots-basicsand callexample.roots.readwith./data/sample.txt(allowed) and/etc/passwd(denied). - In the advanced ffmpeg-studio example, paths are scoped by client roots; if none are provided, it falls back to the bundled
./media.
- All roots must exist and be readable; mcp-bash will not create directories.
- Paths are canonicalized (symlinks resolved where possible) before comparison, and drive letters are normalized on Windows/MSYS.
- Only
file://URIs are accepted from clients; non-local authorities are rejected. - Relative paths in
MCPBASH_ROOTSorconfig/roots.jsonresolve againstMCPBASH_PROJECT_ROOT.
- Paths are percent-decoded, normalized via
realpath, and deduplicated before use. - Late/stale responses are dropped using a generation counter so they cannot overwrite newer roots.