angular/angular-cli · error · Error
The current directory resolves to a workspace outside the al
Error message
The current directory resolves to a workspace outside the allowed MCP roots: ${found}. You can use 'list_projects' to find available workspaces. What it means
Same sandbox check as error 35, but applied to a workspace discovered automatically: after `findAngularJsonDir` locates the nearest angular.json above `process.cwd()`, `isAllowedWorkspacePath` verifies the found directory (after realpath resolution) is inside the MCP client's allowed roots. If the discovered workspace falls outside them, the server refuses to operate and throws this error to keep tool access confined to the opened workspace folders.
Source
Thrown at packages/angular/cli/src/commands/mcp/workspace-utils.ts:193
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);
if (!found) {
throw new Error(
'Could not find an Angular workspace (angular.json) in the current directory. ' +
"You can use 'list_projects' to find available workspaces.",
);
}
if (server && !(await isAllowedWorkspacePath(server, found))) {
throw new Error(
`The current directory resolves to a workspace outside the allowed MCP roots: ${found}. ` +
"You can use 'list_projects' to find available workspaces.",
);
}
workspacePath = found;
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 });
}
}
let projectName = projectNameInput;
if (projectName) {
if (!workspace.projects.has(projectName)) {
throw new Error(View on GitHub (pinned to bb72145f9a)
Solutions
- Open the correct workspace folder in the IDE/MCP client so the discovered angular.json directory is within the allowed roots, then retry
- Call `list_projects` to see which workspaces are allowed and select one explicitly via `workspacePath`
- Remove symlinks causing the resolved real path to fall outside the roots, or add the real target to the workspace
- Relaunch the MCP server with its working directory inside the allowed workspace
Example fix
// before (cwd = /work/repos-a, but IDE opened /work/repos-b) cd /work/repos-a && mcp ng_search // after cd /work/repos-b && mcp ng_search // or open /work/repos-a in the IDE
Defensive patterns
Strategy: validation
Validate before calling
import { existsSync, realpathSync } from 'node:fs';
import { join } from 'node:path';
// allowedRoots: real paths of MCP client workspace folders
function findAngularJsonDir(startDir: string): string | null {
let dir = startDir;
while (true) {
if (existsSync(join(dir, 'angular.json'))) return dir;
const parent = join(dir, '..');
if (parent === dir) return null;
dir = parent;
}
}
const found = findAngularJsonDir(process.cwd());
const allowed = found != null && allowedRoots.some((root) => {
const r = realpathSync(root), f = realpathSync(found);
return f === r || f.startsWith(r + '/');
});
if (!allowed) {
throw new Error(`Discovered workspace ${found} is outside allowed MCP roots; open it in the IDE or pass an allowed workspacePath`);
} 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 {
return await mcp.callTool('ng_search', {});
} catch (e) {
if (String(e?.message).includes('outside the allowed MCP roots')) {
const projects = await mcp.callTool('list_projects', {});
return mcp.callTool('ng_search', { workspacePath: pickAllowedWorkspace(projects) });
}
throw e;
} Prevention
- Start the MCP server from a cwd inside the IDE-opened workspace folders
- Open all relevant project folders (multi-root workspace) so discovery lands inside allowed roots
- Avoid symlinked working directories whose real path falls outside the opened folder
- Use list_projects to confirm which workspaces are allowed before invoking tools
- Pass an explicit, allowed workspacePath instead of relying on cwd discovery
When it happens
Trigger: Invoking an MCP tool without `workspacePath` while `process.cwd()` sits inside (or under a path whose nearest angular.json belongs to) a directory outside the MCP roots — e.g. cwd is a sibling repo, a symlinked directory resolving elsewhere, or the client only opened one of several projects.
Common situations: Terminal/MCP server started from outside the IDE-opened folder; the project is accessed through a symlink into another location; multiple repos side by side with the server launched from the wrong one; the user opened only a subfolder but the angular.json found belongs to a parent outside the roots.
Related errors
- Workspace path is outside the allowed MCP roots: ${workspace
- Workspace path is outside the allowed MCP roots: ${workspace
- Could not find a package.json. Are you in a Node project?
- Could not find ${level} workspace.
- Could not find a ${level} workspace. Are you in a project?
AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30).
Data as JSON: /api/errors/d15a725caedd6b3a.
Report an issue: GitHub.