angular/angular-cli · error · Error
Workspace path is outside the allowed MCP roots
Error message
Workspace path is outside the allowed MCP roots: ${workspacePathInput}. You can use 'list_projects' to find available workspaces. What it means
The Angular CLI MCP server restricts all workspace operations to a configured set of allowed root directories (the MCP roots, derived from the client's workspace folders). Before using an explicitly supplied `workspacePath`, `resolveWorkspaceAndProject` checks it (after realpath resolution) against these roots via `isAllowedWorkspacePath`. If the path is not contained within any allowed root, this error is thrown to prevent the MCP tool from reading or modifying directories outside the sandbox the client approved.
Solutions
- Open the target project's folder (or add it as a workspace folder) in the IDE/MCP client so its real path falls under an allowed MCP root, then retry
- Call the `list_projects` MCP tool to see which workspaces are currently allowed and use one of those paths
- Verify the path has no symlink redirecting outside the allowed roots (the check uses realpathSync on both sides)
- Restart or reconfigure the MCP server so its allowed roots include the directory
Example fix
// before
await mcp.callTool('ng_search', { workspacePath: '/home/me/other-repo/apps/web' });
// after
await mcp.callTool('ng_search', { workspacePath: '/home/me/my-repo/apps/web' }); // opened in the IDE, inside MCP roots Defensive patterns
Strategy: validation
Validate before calling
import { realpathSync } from 'node:fs';
// allowedRoots: string[] obtained from the MCP client/IDE workspace folders
function isInsideAllowedRoots(workspacePath: string, allowedRoots: string[]): boolean {
const real = realpathSync(workspacePath);
return allowedRoots.some((root) => {
const realRoot = realpathSync(root);
return real === realRoot || real.startsWith(realRoot + '/');
});
}
if (!isInsideAllowedRoots(workspacePath, allowedRoots)) {
throw new Error(`Refusing to call MCP tool: ${workspacePath} is outside allowed MCP roots`);
} Type guard
function isPathWithinRoot(childPath: string, rootPath: string): boolean {
const rel = path.relative(path.resolve(rootPath), path.resolve(childPath));
return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));
} Try / catch
try {
await mcp.callTool('ng_search', { workspacePath });
} catch (e) {
if (String(e?.message).includes('outside the allowed MCP roots')) {
// fall back to listing allowed workspaces and picking a valid one
const projects = await mcp.callTool('list_projects', {});
console.warn('Workspace not allowed; available:', projects);
} else {
throw e;
}
} Prevention
- Only pass workspacePath values that match folders opened in the IDE / registered with the MCP server
- Call list_projects first when unsure which paths are permitted
- Resolve symlinks before passing paths — the check compares realpaths
- Keep the MCP server's configured roots in sync with multi-root IDE workspaces
- Avoid passing paths across repository checkouts not opened in the client
When it happens
Trigger: Calling an MCP tool (e.g. find_tests, build, generators) with a `workspacePath` argument pointing to a directory outside the IDE/MCP client's opened workspace folders — or to a path that resolves (via symlink/realpath) outside them — while the `server` context defines allowed roots.
Common situations: Passing an absolute path to another checkout or monorepo on disk while only one project is open in the IDE; the target directory is reached through a symlink whose real target lies outside the roots; a moved/renamed project folder that is no longer under the opened workspace; running the MCP server standalone without roots configured to include the path.
Related errors
- The current directory resolves to a workspace outside the…
- Workspace path is outside the allowed MCP roots
- A builder is not set for target
- A workspace is required for this command.
- Access denied: glob pattern
AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30).
Data as JSON: /api/errors/c34fafe04038cc34.
Report an issue: GitHub.
Appendix: source
Thrown at packages/angular/cli/src/commands/mcp/workspace-utils.ts:165
let workspacePath: string;
let workspace: AngularWorkspace;
if (workspacePathInput) {
if (!host.existsSync(workspacePathInput)) {
throw new Error(
`Workspace path does not exist: ${workspacePathInput}. ` +
"You can use 'list_projects' to find available workspaces.",
);
}
if (!host.existsSync(join(workspacePathInput, 'angular.json'))) {
throw new Error(
`No angular.json found at ${workspacePathInput}. ` +
"You can use 'list_projects' to find available workspaces.",
);
}
if (server) {
if (!(await isAllowedWorkspacePath(server, workspacePathInput))) {
throw new Error(
`Workspace path is outside the allowed MCP roots: ${workspacePathInput}. ` +
"You can use 'list_projects' to find available workspaces.",
);
}
}
workspacePath = workspacePathInput;
const configPath = join(workspacePath, 'angular.json');
try {
workspace = await AngularWorkspace.load(configPath);
} catch (e) {
throw new Error(`Failed to load workspace configuration at ${configPath}`, { cause: e });
}
} else if (mcpWorkspace) {
workspace = mcpWorkspace;
workspacePath = workspace.basePath;
} else {
const found = findAngularJsonDir(process.cwd(), host);View on GitHub (pinned to bb72145f9a)