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

  1. Open the correct workspace folder in the IDE/MCP client so the discovered angular.json directory is within the allowed roots, then retry
  2. Call `list_projects` to see which workspaces are allowed and select one explicitly via `workspacePath`
  3. Remove symlinks causing the resolved real path to fall outside the roots, or add the real target to the workspace
  4. 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

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


AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30). Data as JSON: /api/errors/d15a725caedd6b3a. Report an issue: GitHub.