Skip to main content
Glama
nrwl

Nx MCP Server

Official
by nrwl
nx-project-details-select.test.ts6.59 kB
import { cleanupNxWorkspace, createInvokeMCPInspectorCLI, defaultVersion, e2eCwd, newWorkspace, simpleReactWorkspaceOptions, uniq, } from '@nx-console/shared-e2e-utils'; import { rmSync } from 'node:fs'; import { join } from 'node:path'; describe('nx_project_details select', () => { let invokeMCPInspectorCLI: Awaited< ReturnType<typeof createInvokeMCPInspectorCLI> >; const workspaceName = uniq('nx-mcp-project-details-select'); const testWorkspacePath = join(e2eCwd, workspaceName); beforeAll(async () => { newWorkspace({ name: workspaceName, options: simpleReactWorkspaceOptions, }); invokeMCPInspectorCLI = await createInvokeMCPInspectorCLI( e2eCwd, workspaceName, ); }); afterAll(async () => { await cleanupNxWorkspace(testWorkspacePath, defaultVersion); rmSync(testWorkspacePath, { recursive: true, force: true }); }); it('should return full project details when no select is provided', () => { const result = invokeMCPInspectorCLI( testWorkspacePath, '--method tools/call', '--tool-name nx_project_details', `--tool-arg projectName="${workspaceName}"`, ); // Should have 3 content blocks: Project Details (without targets), Available Targets (compressed), and External Dependencies expect(result.content).toHaveLength(3); expect(result.content[0]?.text).toContain('Project Details:'); expect(result.content[0]?.text).toContain('"name":'); // Targets should NOT be in the JSON anymore expect(result.content[0]?.text).not.toContain('"targets":'); // Second block should be compressed targets expect(result.content[1]?.text).toContain( 'Available Targets (compressed view)', ); expect(result.content[1]?.text).toContain( 'To see full configuration for a specific target', ); // Cache should only appear when it's false (token efficiency) // So we should see "cache: false" somewhere, but not "cache: true" expect(result.content[1]?.text).not.toContain('cache: true'); // Third block should be External Dependencies expect(result.content[2]?.text).toContain('External Dependencies:'); }); it('should select to root path using dot notation', () => { const result = invokeMCPInspectorCLI( testWorkspacePath, '--method tools/call', '--tool-name nx_project_details', `--tool-arg projectName="${workspaceName}"`, '--tool-arg select="root"', ); // Should have 1 content block with the selected value expect(result.content).toHaveLength(1); const text = result.content[0]?.text; // Should start with "Project Details: " prefix and contain the root value expect(text).toContain('Project Details:'); expect(text).toContain('"."'); // Should not contain other project data expect(text).not.toContain('"targets"'); expect(text).not.toContain('"name"'); }); it('should select to name field', () => { const result = invokeMCPInspectorCLI( testWorkspacePath, '--method tools/call', '--tool-name nx_project_details', `--tool-arg projectName="${workspaceName}"`, '--tool-arg select="name"', ); expect(result.content).toHaveLength(1); const text = result.content[0]?.text; expect(text).toContain('Project Details:'); expect(text).toContain(`"${workspaceName}"`); }); it('should select to nested targets.build path', () => { const result = invokeMCPInspectorCLI( testWorkspacePath, '--method tools/call', '--tool-name nx_project_details', `--tool-arg projectName="${workspaceName}"`, '--tool-arg select="targets.build"', ); expect(result.content).toHaveLength(1); const text = result.content[0]?.text; // Should contain build target configuration expect(text).toContain('"executor"'); expect(text).toContain('"options"'); // Should not contain the full targets object with other targets expect(text).not.toContain('"targets"'); }); it('should select to deeply nested targets.build.executor path', () => { const result = invokeMCPInspectorCLI( testWorkspacePath, '--method tools/call', '--tool-name nx_project_details', `--tool-arg projectName="${workspaceName}"`, '--tool-arg select="targets.build.executor"', ); expect(result.content).toHaveLength(1); const text = result.content[0]?.text; // Should be just the executor string expect(text).toContain('nx:'); expect(text).not.toContain('"options"'); }); it('should select to tags array', () => { const result = invokeMCPInspectorCLI( testWorkspacePath, '--method tools/call', '--tool-name nx_project_details', `--tool-arg projectName="${workspaceName}"`, '--tool-arg select="tags"', ); expect(result.content).toHaveLength(1); const text = result.content[0]?.text; // Should contain the "Project Details:" prefix and the array expect(text).toContain('Project Details:'); expect(text).toContain('['); expect(text).toContain(']'); }); it('should select to array element using bracket notation tags[0]', () => { const result = invokeMCPInspectorCLI( testWorkspacePath, '--method tools/call', '--tool-name nx_project_details', `--tool-arg projectName="${workspaceName}"`, '--tool-arg select="tags[0]"', ); expect(result.content).toHaveLength(1); const text = result.content[0]?.text; // Should contain the "Project Details:" prefix and a single string value (first tag) expect(text).toContain('Project Details:'); expect(text).toContain('"'); }); it('should return error for invalid path', () => { const result = invokeMCPInspectorCLI( testWorkspacePath, '--method tools/call', '--tool-name nx_project_details', `--tool-arg projectName="${workspaceName}"`, '--tool-arg select="nonexistent.path.to.nowhere"', ); expect(result.isError).toBe(true); expect(result.content[0]?.text).toContain( 'Path "nonexistent.path.to.nowhere" not found', ); }); it('should return error for nonexistent project', () => { const result = invokeMCPInspectorCLI( testWorkspacePath, '--method tools/call', '--tool-name nx_project_details', '--tool-arg projectName="nonexistent-project"', '--tool-arg select="root"', ); expect(result.isError).toBe(true); expect(result.content[0]?.text).toContain( 'Project nonexistent-project not found', ); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/nrwl/nx-console'

If you have feedback or need assistance with the MCP directory API, please join our Discord server