Skip to content

Commit 619fa8a

Browse files
Merge pull request #14 from push-based/feature/add-listing-tool
feat(angular-mcp-server): add listing tool, extend listing api
2 parents f32cd79 + c40f6c8 commit 619fa8a

File tree

7 files changed

+398
-36
lines changed

7 files changed

+398
-36
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: 115 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,56 @@
11
import { ToolSchemaOptions } from '@push-based/models';
2-
import { createHandler } from '../shared/utils/handler-helpers.js';
32
import {
4-
createComponentInputSchema,
5-
COMMON_ANNOTATIONS,
6-
} from '../shared/models/schema-helpers.js';
3+
createHandler,
4+
BaseHandlerOptions,
5+
} from '../shared/utils/handler-helpers.js';
6+
import { COMMON_ANNOTATIONS } from '../shared/models/schema-helpers.js';
77
import { getComponentPathsInfo } from './utils/paths-helpers.js';
88
import { getComponentDocPathsForName } from './utils/doc-helpers.js';
9-
import { validateComponentName } from '../shared/utils/component-validation.js';
9+
import {
10+
validateComponentName,
11+
componentNameToKebabCase,
12+
} from '../shared/utils/component-validation.js';
1013
import { resolveCrossPlatformPath } from '../shared/utils/cross-platform-path.js';
1114
import * as fs from 'fs';
1215
import * as path from 'path';
1316

14-
interface DsComponentDataOptions {
17+
interface DsComponentDataOptions extends BaseHandlerOptions {
18+
componentName: string;
19+
sections?: string[];
20+
}
21+
22+
interface DsComponentData {
1523
componentName: string;
24+
implementation: string[];
25+
documentation: string[];
26+
stories: string[];
27+
importPath: string;
1628
}
1729

1830
export const getDsComponentDataToolSchema: ToolSchemaOptions = {
1931
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-
),
32+
description: `Return comprehensive data for a DS component including implementation files, documentation files, stories files, and import path.`,
33+
inputSchema: {
34+
type: 'object',
35+
properties: {
36+
componentName: {
37+
type: 'string',
38+
description:
39+
'The class name of the component to get data for (e.g., DsBadge)',
40+
},
41+
sections: {
42+
type: 'array',
43+
items: {
44+
type: 'string',
45+
enum: ['implementation', 'documentation', 'stories', 'all'],
46+
},
47+
description:
48+
'Sections to include in the response. Options: "implementation", "documentation", "stories", "all". Defaults to ["all"] if not specified.',
49+
default: ['all'],
50+
},
51+
},
52+
required: ['componentName'],
53+
},
2454
annotations: {
2555
title: 'Get Design System Component Data',
2656
...COMMON_ANNOTATIONS.readOnly,
@@ -45,7 +75,7 @@ function getAllFilesInDirectory(dirPath: string): string[] {
4575
}
4676
}
4777
} catch {
48-
// Ignore directories that can't be read
78+
return;
4979
}
5080
}
5181

@@ -56,38 +86,89 @@ function getAllFilesInDirectory(dirPath: string): string[] {
5686
return files;
5787
}
5888

89+
function findStoriesFiles(componentPath: string): string[] {
90+
const storiesFiles: string[] = [];
91+
92+
try {
93+
if (fs.existsSync(componentPath)) {
94+
const items = fs.readdirSync(componentPath);
95+
96+
for (const item of items) {
97+
const fullPath = path.join(componentPath, item);
98+
const stat = fs.statSync(fullPath);
99+
100+
if (stat.isFile() && item.endsWith('.stories.ts')) {
101+
storiesFiles.push(fullPath);
102+
}
103+
}
104+
}
105+
} catch {
106+
return storiesFiles;
107+
}
108+
109+
return storiesFiles;
110+
}
111+
59112
export const getDsComponentDataHandler = createHandler<
60113
DsComponentDataOptions,
61-
any
114+
DsComponentData
62115
>(
63116
getDsComponentDataToolSchema.name,
64-
async ({ componentName }, { cwd, uiRoot, storybookDocsRoot }) => {
117+
async (
118+
{ componentName, sections = ['all'] },
119+
{ cwd, uiRoot, storybookDocsRoot },
120+
) => {
65121
try {
66122
validateComponentName(componentName);
67123

68-
// Get component paths info
69-
const pathsInfo = getComponentPathsInfo(componentName, uiRoot, cwd);
124+
const includeAll = sections.includes('all');
125+
const includeImplementation =
126+
includeAll || sections.includes('implementation');
127+
const includeDocumentation =
128+
includeAll || sections.includes('documentation');
129+
const includeStories = includeAll || sections.includes('stories');
70130

71-
// Get all implementation files in src directory
72-
const srcFiles = getAllFilesInDirectory(pathsInfo.srcPath);
73-
const implementationFiles = srcFiles.map((file) => `file://${file}`);
131+
const pathsInfo = getComponentPathsInfo(componentName, uiRoot, cwd);
74132

75-
// Get documentation paths
76-
const docsBasePath = resolveCrossPlatformPath(cwd, storybookDocsRoot);
77-
const docPaths = getComponentDocPathsForName(docsBasePath, componentName);
133+
let implementationFiles: string[] = [];
134+
if (includeImplementation) {
135+
const srcFiles = getAllFilesInDirectory(pathsInfo.srcPath);
136+
implementationFiles = srcFiles.map((file) => `file://${file}`);
137+
}
78138

79139
const documentationFiles: string[] = [];
80-
if (fs.existsSync(docPaths.paths.api)) {
81-
documentationFiles.push(`file://${docPaths.paths.api}`);
140+
if (includeDocumentation) {
141+
const docsBasePath = resolveCrossPlatformPath(cwd, storybookDocsRoot);
142+
const docPaths = getComponentDocPathsForName(
143+
docsBasePath,
144+
componentName,
145+
);
146+
147+
if (fs.existsSync(docPaths.paths.api)) {
148+
documentationFiles.push(`file://${docPaths.paths.api}`);
149+
}
150+
if (fs.existsSync(docPaths.paths.overview)) {
151+
documentationFiles.push(`file://${docPaths.paths.overview}`);
152+
}
82153
}
83-
if (fs.existsSync(docPaths.paths.overview)) {
84-
documentationFiles.push(`file://${docPaths.paths.overview}`);
154+
155+
let storiesFilePaths: string[] = [];
156+
if (includeStories) {
157+
const docsBasePath = resolveCrossPlatformPath(cwd, storybookDocsRoot);
158+
const componentFolderName = componentNameToKebabCase(componentName);
159+
const storiesComponentFolderPath = path.join(
160+
docsBasePath,
161+
componentFolderName,
162+
);
163+
const storiesFiles = findStoriesFiles(storiesComponentFolderPath);
164+
storiesFilePaths = storiesFiles.map((file) => `file://${file}`);
85165
}
86166

87167
return {
88168
componentName,
89169
implementation: implementationFiles,
90170
documentation: documentationFiles,
171+
stories: storiesFilePaths,
91172
importPath: pathsInfo.importPath,
92173
};
93174
} catch (ctx) {
@@ -99,7 +180,6 @@ export const getDsComponentDataHandler = createHandler<
99180
(result) => {
100181
const messages: string[] = [];
101182

102-
// Implementation section
103183
if (result.implementation && result.implementation.length > 0) {
104184
messages.push('Implementation');
105185
messages.push('');
@@ -109,7 +189,6 @@ export const getDsComponentDataHandler = createHandler<
109189
messages.push('');
110190
}
111191

112-
// Documentation section
113192
if (result.documentation && result.documentation.length > 0) {
114193
messages.push('Documentation');
115194
messages.push('');
@@ -119,7 +198,15 @@ export const getDsComponentDataHandler = createHandler<
119198
messages.push('');
120199
}
121200

122-
// Import path section
201+
if (result.stories && result.stories.length > 0) {
202+
messages.push('Stories');
203+
messages.push('');
204+
result.stories.forEach((file: string) => {
205+
messages.push(file);
206+
});
207+
messages.push('');
208+
}
209+
123210
if (result.importPath) {
124211
messages.push('Import path');
125212
messages.push('');

0 commit comments

Comments
 (0)