Skip to content

Commit 73fd3ad

Browse files
committed
feat(angular-mcp-server): add listing tool, extend listing api
1 parent f32cd79 commit 73fd3ad

File tree

7 files changed

+375
-32
lines changed

7 files changed

+375
-32
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ A Model Context Protocol (MCP) server that provides Angular project analysis and
99
- **Dependency Mapping**: Map component dependencies across modules, templates, and styles
1010
- **ESLint Integration**: Lint Angular files with automatic ESLint configuration discovery
1111
- **Project Analysis**: Analyze buildable/publishable libraries and validate import paths
12-
- **Component Documentation**: Retrieve component data and documentation
12+
- **Component Documentation**: Retrieve component data and documentation, list available components
1313

1414
## Use Cases
1515

@@ -135,6 +135,8 @@ my-angular-workspace/
135135

136136
### Component Analysis
137137

138+
- **`list-ds-components`**: List all available Design System components in the project with their file paths and metadata
139+
138140
- **`get-ds-component-data`**: Return data for a component including implementation files, documentation files, and import path
139141

140142
- **`build-component-usage-graph`**: Maps where given Angular components are imported (modules, specs, templates, styles) so refactors touch every file

docs/component-refactoring-flow.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ This document describes a 3-step AI-assisted component refactoring process for i
99
2. **Refactor Component** → Execute approved checklist items and implement changes
1010
3. **Validate Component** → Verify improvements through contract comparison and scoring
1111

12-
The process includes two quality gates where human review and approval are required.
12+
The process includes two quality gates where human review and approval are required. When refactoring involves Design System components, the process can leverage selective data retrieval to access only the specific component information needed (implementation, documentation, or stories).
1313

1414
## Prerequisites
1515

@@ -159,6 +159,11 @@ At this point, all checklist items have been processed. You must review the refa
159159
- Returns: contract path with component's public API, DOM structure, and styles
160160
- Purpose: Establish baseline for validation comparison
161161

162+
- `get-ds-component-data` - Retrieves Design System component information when needed
163+
- Parameters: `componentName`, `sections` (optional) - Array of sections to include: "implementation", "documentation", "stories", "all"
164+
- Returns: Selective component data based on refactoring needs
165+
- Purpose: Access DS component documentation and examples for proper implementation patterns
166+
162167
### Flow
163168

164169
> You don't need to manually perform any of the listed actions except providing the initial parameters.

docs/ds-refactoring-flow.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,13 @@ Before proceeding to Phase 3, you must review the comprehensive migration plan.
199199
200200
### Tools used
201201

202+
- `list-ds-components` - Lists all available Design System components in the project
203+
- Parameters: `sections` (optional) - Array of sections to include: "implementation", "documentation", "stories", "all"
204+
- Returns: Complete inventory of DS components with their file paths and metadata
205+
- Provides: Overview of available components for comprehensive migration planning
206+
202207
- `get-ds-component-data` - Retrieves comprehensive component information for all involved components
208+
- Parameters: `componentName`, `sections` (optional) - Array of sections to include: "implementation", "documentation", "stories", "all"
203209
- Returns: Complete implementation files, documentation files, import paths for multiple components
204210
- Provides: Component source code, API documentation, usage examples across scope
205211

@@ -285,7 +291,13 @@ Before proceeding to Phase 3, you must review the migration plan.
285291
286292
### Tools used
287293

294+
- `list-ds-components` - Lists all available Design System components in the project
295+
- Parameters: `sections` (optional) - Array of sections to include: "implementation", "documentation", "stories", "all"
296+
- Returns: Complete inventory of DS components with their file paths and metadata
297+
- Provides: Overview of available components for migration planning
298+
288299
- `get-ds-component-data` - Retrieves comprehensive component information
300+
- Parameters: `componentName`, `sections` (optional) - Array of sections to include: "implementation", "documentation", "stories", "all"
289301
- Returns: implementation files, documentation files, import paths
290302
- Provides: component source code, API documentation, usage examples
291303

docs/tools.md

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,23 @@ This document provides comprehensive guidance for AI agents working with Angular
4545

4646
### 📚 Component Information Tools
4747

48+
#### `list-ds-components`
49+
**Purpose**: Lists all available Design System components in the project with their file paths and metadata
50+
**AI Usage**: Discover available DS components before starting migration or analysis workflows
51+
**Key Parameters**:
52+
- `sections`: Array of sections to include - `"implementation"`, `"documentation"`, `"stories"`, or `"all"` (default: `["all"]`)
53+
**Output**: Complete inventory of DS components with their implementation files, documentation files, stories files, and import paths
54+
**Best Practice**: Use as the first step to understand the DS component landscape before targeted analysis
55+
56+
#### `get-ds-component-data`
57+
**Purpose**: Returns comprehensive data for a specific DS component including implementation files, documentation files, stories files, and import path
58+
**AI Usage**: Get detailed information about a specific component for analysis or migration planning
59+
**Key Parameters**:
60+
- `componentName`: DS component class name (e.g., `DsBadge`)
61+
- `sections`: Array of sections to include - `"implementation"`, `"documentation"`, `"stories"`, or `"all"` (default: `["all"]`)
62+
**Output**: Structured data with file paths for implementation, documentation, stories, and import information
63+
**Best Practice**: Use selective sections to optimize performance when you only need specific types of files
64+
4865
#### `get-component-docs`
4966
**Purpose**: Retrieves MDX documentation for DS components
5067
**AI Usage**: Access official component documentation to understand proper usage patterns
@@ -127,16 +144,18 @@ This document provides comprehensive guidance for AI agents working with Angular
127144

128145
### 1. Discovery & Analysis Workflow
129146
```
130-
1. report-violations → Identify all violations
131-
2. get-project-dependencies → Analyze project structure
147+
1. list-ds-components → Discover available DS components
148+
2. report-violations → Identify all violations
149+
3. get-project-dependencies → Analyze project structure
132150
```
133151

134152
### 2. Planning & Preparation Workflow
135153
```
136-
1. build-component-usage-graph → Map component relationships
137-
2. get-component-docs → Review proper usage patterns
138-
3. get-component-paths → Verify import paths
139-
4. build_component_contract → Create baseline contracts
154+
1. get-ds-component-data → Get comprehensive component information
155+
2. build-component-usage-graph → Map component relationships
156+
3. get-component-docs → Review proper usage patterns
157+
4. get-component-paths → Verify import paths
158+
5. build_component_contract → Create baseline contracts
140159
```
141160

142161
### 3. Refactoring & Validation Workflow
@@ -173,6 +192,7 @@ This document provides comprehensive guidance for AI agents working with Angular
173192

174193
- Use `groupBy: "folder"` for large codebases to reduce output size
175194
- Limit `violationFiles` arrays to relevant files only
195+
- Use selective `sections` parameter in `get-ds-component-data` and `list-ds-components` to retrieve only needed data types
176196
- Cache component documentation between related operations
177197
- Run validation tools in parallel when possible
178198

packages/angular-mcp-server/src/lib/tools/ds/component/get-ds-component-data.tool.ts

Lines changed: 104 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,50 @@
11
import { ToolSchemaOptions } from '@push-based/models';
2-
import { createHandler } from '../shared/utils/handler-helpers.js';
2+
import { createHandler, BaseHandlerOptions } from '../shared/utils/handler-helpers.js';
33
import {
4-
createComponentInputSchema,
54
COMMON_ANNOTATIONS,
65
} from '../shared/models/schema-helpers.js';
76
import { getComponentPathsInfo } from './utils/paths-helpers.js';
87
import { getComponentDocPathsForName } from './utils/doc-helpers.js';
9-
import { validateComponentName } from '../shared/utils/component-validation.js';
8+
import { validateComponentName, componentNameToKebabCase } from '../shared/utils/component-validation.js';
109
import { resolveCrossPlatformPath } from '../shared/utils/cross-platform-path.js';
1110
import * as fs from 'fs';
1211
import * as path from 'path';
1312

14-
interface DsComponentDataOptions {
13+
interface DsComponentDataOptions extends BaseHandlerOptions {
1514
componentName: string;
15+
sections?: string[];
16+
}
17+
18+
interface DsComponentData {
19+
componentName: string;
20+
implementation: string[];
21+
documentation: string[];
22+
stories: string[];
23+
importPath: string;
1624
}
1725

1826
export const getDsComponentDataToolSchema: ToolSchemaOptions = {
1927
name: 'get-ds-component-data',
20-
description: `Return comprehensive data for a DS component including implementation files, documentation files, and import path.`,
21-
inputSchema: createComponentInputSchema(
22-
'The class name of the component to get data for (e.g., DsBadge)',
23-
),
28+
description: `Return comprehensive data for a DS component including implementation files, documentation files, stories files, and import path.`,
29+
inputSchema: {
30+
type: 'object',
31+
properties: {
32+
componentName: {
33+
type: 'string',
34+
description: 'The class name of the component to get data for (e.g., DsBadge)',
35+
},
36+
sections: {
37+
type: 'array',
38+
items: {
39+
type: 'string',
40+
enum: ['implementation', 'documentation', 'stories', 'all'],
41+
},
42+
description: 'Sections to include in the response. Options: "implementation", "documentation", "stories", "all". Defaults to ["all"] if not specified.',
43+
default: ['all'],
44+
},
45+
},
46+
required: ['componentName'],
47+
},
2448
annotations: {
2549
title: 'Get Design System Component Data',
2650
...COMMON_ANNOTATIONS.readOnly,
@@ -56,38 +80,84 @@ function getAllFilesInDirectory(dirPath: string): string[] {
5680
return files;
5781
}
5882

83+
function findStoriesFiles(componentPath: string): string[] {
84+
const storiesFiles: string[] = [];
85+
86+
try {
87+
if (fs.existsSync(componentPath)) {
88+
const items = fs.readdirSync(componentPath);
89+
90+
for (const item of items) {
91+
const fullPath = path.join(componentPath, item);
92+
const stat = fs.statSync(fullPath);
93+
94+
// Only look for .stories.ts files directly in the component folder, not in subdirectories
95+
if (stat.isFile() && item.endsWith('.stories.ts')) {
96+
storiesFiles.push(fullPath);
97+
}
98+
}
99+
}
100+
} catch {
101+
// Ignore directories that can't be read
102+
}
103+
104+
return storiesFiles;
105+
}
106+
59107
export const getDsComponentDataHandler = createHandler<
60108
DsComponentDataOptions,
61-
any
109+
DsComponentData
62110
>(
63111
getDsComponentDataToolSchema.name,
64-
async ({ componentName }, { cwd, uiRoot, storybookDocsRoot }) => {
112+
async ({ componentName, sections = ['all'] }, { cwd, uiRoot, storybookDocsRoot }) => {
65113
try {
66114
validateComponentName(componentName);
67115

116+
// Determine which sections to include
117+
const includeAll = sections.includes('all');
118+
const includeImplementation = includeAll || sections.includes('implementation');
119+
const includeDocumentation = includeAll || sections.includes('documentation');
120+
const includeStories = includeAll || sections.includes('stories');
121+
68122
// Get component paths info
69123
const pathsInfo = getComponentPathsInfo(componentName, uiRoot, cwd);
70124

71-
// Get all implementation files in src directory
72-
const srcFiles = getAllFilesInDirectory(pathsInfo.srcPath);
73-
const implementationFiles = srcFiles.map((file) => `file://${file}`);
74-
75-
// Get documentation paths
76-
const docsBasePath = resolveCrossPlatformPath(cwd, storybookDocsRoot);
77-
const docPaths = getComponentDocPathsForName(docsBasePath, componentName);
125+
// Get all implementation files in src directory (if requested)
126+
let implementationFiles: string[] = [];
127+
if (includeImplementation) {
128+
const srcFiles = getAllFilesInDirectory(pathsInfo.srcPath);
129+
implementationFiles = srcFiles.map((file) => `file://${file}`);
130+
}
78131

132+
// Get documentation paths (if requested)
79133
const documentationFiles: string[] = [];
80-
if (fs.existsSync(docPaths.paths.api)) {
81-
documentationFiles.push(`file://${docPaths.paths.api}`);
134+
if (includeDocumentation) {
135+
const docsBasePath = resolveCrossPlatformPath(cwd, storybookDocsRoot);
136+
const docPaths = getComponentDocPathsForName(docsBasePath, componentName);
137+
138+
if (fs.existsSync(docPaths.paths.api)) {
139+
documentationFiles.push(`file://${docPaths.paths.api}`);
140+
}
141+
if (fs.existsSync(docPaths.paths.overview)) {
142+
documentationFiles.push(`file://${docPaths.paths.overview}`);
143+
}
82144
}
83-
if (fs.existsSync(docPaths.paths.overview)) {
84-
documentationFiles.push(`file://${docPaths.paths.overview}`);
145+
146+
// Get stories files (if requested)
147+
let storiesFilePaths: string[] = [];
148+
if (includeStories) {
149+
const docsBasePath = resolveCrossPlatformPath(cwd, storybookDocsRoot);
150+
const componentFolderName = componentNameToKebabCase(componentName);
151+
const storiesComponentFolderPath = path.join(docsBasePath, componentFolderName);
152+
const storiesFiles = findStoriesFiles(storiesComponentFolderPath);
153+
storiesFilePaths = storiesFiles.map((file) => `file://${file}`);
85154
}
86155

87156
return {
88157
componentName,
89158
implementation: implementationFiles,
90159
documentation: documentationFiles,
160+
stories: storiesFilePaths,
91161
importPath: pathsInfo.importPath,
92162
};
93163
} catch (ctx) {
@@ -99,7 +169,7 @@ export const getDsComponentDataHandler = createHandler<
99169
(result) => {
100170
const messages: string[] = [];
101171

102-
// Implementation section
172+
// Implementation section (only show if it has content or was explicitly requested)
103173
if (result.implementation && result.implementation.length > 0) {
104174
messages.push('Implementation');
105175
messages.push('');
@@ -109,7 +179,7 @@ export const getDsComponentDataHandler = createHandler<
109179
messages.push('');
110180
}
111181

112-
// Documentation section
182+
// Documentation section (only show if it has content or was explicitly requested)
113183
if (result.documentation && result.documentation.length > 0) {
114184
messages.push('Documentation');
115185
messages.push('');
@@ -119,7 +189,17 @@ export const getDsComponentDataHandler = createHandler<
119189
messages.push('');
120190
}
121191

122-
// Import path section
192+
// Stories section (only show if it has content or was explicitly requested)
193+
if (result.stories && result.stories.length > 0) {
194+
messages.push('Stories');
195+
messages.push('');
196+
result.stories.forEach((file: string) => {
197+
messages.push(file);
198+
});
199+
messages.push('');
200+
}
201+
202+
// Import path section (always show if available)
123203
if (result.importPath) {
124204
messages.push('Import path');
125205
messages.push('');

0 commit comments

Comments
 (0)