angular/angular-cli · error · Error

Workspace path is outside the allowed MCP roots: ${workspace

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.

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)

Solutions

  1. 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
  2. Call the `list_projects` MCP tool to see which workspaces are currently allowed and use one of those paths
  3. Verify the path has no symlink redirecting outside the allowed roots (the check uses realpathSync on both sides)
  4. 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

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


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