MCP server that exposes Angular Modernizer capabilities as 41 structured tools for AI assistants.
The @angular-modernizer/adapter-mcp package provides a Model Context Protocol (MCP) server for Angular codebase modernization. Built on the core Angular Modernization Platform, this adapter enables AI assistants to perform analysis, generate migration strategies, and execute safe transformations.
Tools are designed for LLM consumption with structured I/O, pre-validation, automatic backup, build validation, and rollback on failure.
AI Assistant (Claude/Copilot)
|
| MCP over stdio (JSON-RPC 2.0, MCP TypeScript SDK)
| protocol eras 2025-06-18 / 2025-11-25 (initialize), 2026-07-28 (server/discover)
v
MCP Server (adapter-mcp)
- 41 Tools (analysis, planning, transformation,
build and validation, rollback, feedback, bug investigation)
- Input validation against closed JSON schemas
- structuredContent validated against each outputSchema, plus a summary text
- Native MCP progress and cancellation
- Shared ts-morph ProjectCache (investigation tools, build impact, plan-migration)
| |
| Kernel per call | direct calls
| (scans, transform-code, ...) | (14 investigation tools)
v |
Core Platform (Kernel + Plugins) |
- Analysis rules (52) |
- Architecture: 17 |
- Angular: 28 |
- SOLID: 7 |
- Transformations (26 types via transform-code)
- Safety envelope: backup, type check, rollback
- Caching, worker parallelism, workflow engine
| |
| context.api |
v v
Public API (@angular-modernizer/api)
- Analysis and transformation building blocks
- Investigation: usages, call graph, types, templates, forms, i18n
|
| ts-morph AST, TypeScript type checker, @angular/compiler (templates)
v
TypeScript / Angular Project
- Source files and templates
- Type checking
- Semantic analysis
The server runs on the official MCP TypeScript SDK (@modelcontextprotocol/server) over stdio and serves both protocol eras on one connection type: clients that open with initialize get the revision they ask for (2025-06-18, 2025-11-25), clients that open with server/discover get 2026-07-28. Tool results are identical in both eras. Only the tools capability is announced. A response above 4 MB is replaced by an error result that names the tool and how to narrow the request.
Arguments are validated against each tool's input schema (JSON Schema 2020-12) before the tool runs. Wrong types, missing required arguments and unknown argument names come back as an error result (isError: true) naming the offending argument. A tool that reports a failure in its result (success: false or status: "failed", e.g. a build that exits with an error) also answers with isError: true; the result details stay in structuredContent.
Every tool has an output schema and answers with structuredContent: the result object, which always carries a summary string. The text content holds only that summary (repeating the JSON there made the answers 1.6 times as large; Claude Code shows the model structuredContent). structuredContent is validated against the output schema; a result that does not match comes back as an error result. Tools that run a command (run-angular-cli, run-build, run-schematic) keep the full output in the result and repeat only its last lines in the summary on failure. orchestrate-migration reports its step counts in counts and workflowId at the top level.
Set ANGULAR_MODERNIZER_DEBUG=1 in the server environment for diagnostics: a debug log ./mcp-server.log in the working directory and a health check on http://localhost:9999/health and /status. Both are off by default.
cd packages/adapter-mcp
pnpm install
pnpm build
pnpm start
Create .angular-modernizer.json in your project root. Only build is required; per-tool defaults go under
tools (full reference: docs/CONFIGURATION.md, schema: packages/core/schemas/angular-modernizer.schema.json):
{
"build": {
"command": "ng build",
"mode": "incremental"
},
"tools": {
"analyze-project": {
"excludePatterns": ["**/node_modules/**", "**/dist/**"]
},
"scan-architecture": {
"maxFiles": 500
}
}
}
The schema allows no unknown top-level keys: tool options outside tools make the file fail validation
(ConfigValidationError), and none of its settings apply.
The server entry point is dist/cli.js (dist/index.js only exports the tool classes). Claude Code:
claude mcp add angular-modernizer npx @angular-modernizer/adapter-mcp
Or point a client at a local build, e.g. .mcp.json / claude_desktop_config.json:
{
"mcpServers": {
"angular-modernizer": {
"command": "node",
"args": ["--expose-gc", "/path/to/tsanalyzer/packages/adapter-mcp/dist/cli.js"],
"cwd": "/path/to/your/angular/project"
}
}
}
--expose-gc lets the ProjectCache collect garbage after evicting a project. cli.js also takes
--max-projects N and --max-heap-mb N (defaults 3 and 2048; the heap limit also applies to the scan worker) and
--scan-worker 0 (scans on the main thread instead of a worker thread). A running client keeps the old code in memory
after a rebuild; reconnect, or check server-status (build.rebuiltSinceStart).
| Tool | Purpose | Rules | Cache | Time |
|---|---|---|---|---|
| analyze-project | Framework/architecture detection | - | yes | 2-5s |
| scan-architecture | Architecture violations incl. import cycles and layer boundaries | 17 | yes | 5-30s |
| scan-solid | SOLID principle violations | 7 | yes | 3-15s |
| scan-angular | Angular best practices | 28 | yes | 5-20s |
| scan-all | Combined analysis (all plugins) | 52 | yes | 10-45s |
| compare-health | Full scan compared with the previous run: new, fixed and unchanged violations per rule and file; answers with structuredContent |
52 | yes (scan-all cache) | scan-all time |
| analyze-core-to-shared | Dependency violation analysis | - | yes | 3-10s |
| analyze-parser-performance | Parser metrics from feedback sessions | - | no | varies |
| extract-libraries | Library extraction candidates (shared folders, secondary entry points) | - | no | varies |
| learn-patterns | Pattern discovery with AST heuristics, stored in a knowledge base | - | yes | 10-60s |
The scans, analyze-project, analyze-core-to-shared and extract-libraries keep their numbers in counts (for the scans totalViolations, analyzedFiles, bySeverity, byCategory, byRule, always over all violations); summary is a short text with the totals, the largest rules and categories, the first five entries and the returned page. violations holds only the page set by maxResults and resultOffset, pagination says what was cut.
Detects framework (Angular CLI, Nx), analyzes architecture patterns, identifies layers, and discovers project structure including PWA/offline capabilities.
Key features:
Runs 17 architecture rules detecting import cycles (solid:circular-dependency, project-wide value-import graph with NG0919 risk flag), god objects, layer boundary violations, and architectural anti-patterns.
Key features:
maxDurationMs (default 300000, 0 = off): checked between files; on overrun the scan returns what it has with execution.incomplete, skippedFiles and a note. execution.ruleTimings lists time per rule, slowest first. Note that maxFiles defaults to 100.maxResults (default 1000) and resultOffset page the violations; counts cover all of them, pagination.hasMore says whether to fetch the next page. Pass rules (exact rule ids such as solid:circular-dependency) for a focused scan.notifications/progress, with a progressToken) and cancellation between files, see Progress and Cancellation. streaming (deprecated) defaults to false: the call returns the violations. With streaming: true it returns an operationId at once and get-operation-progress returns the result.Runs 7 SOLID principle rules detecting dependency inversion, single responsibility, Liskov substitution, open/closed, and interface segregation violations.
Key features:
Runs 28 Angular-specific rules detecting OnPush violations, RxJS anti-patterns, performance issues, and framework best practice violations.
Key features:
Runs all 52 analysis rules (17 architecture + 7 SOLID + 28 Angular) with its own cache in .angular-modernizer-cache/all/.
Key features:
Runs the scan-all scan over every violation (no result window), compares it with the snapshot of the previous run and stores the current run as the new snapshot.
Key features:
.angular-modernizer-cache/health/last-run.json (snapshotPath overrides), git-ignored with the cachetotals, byRule, byFile, newViolations, fixedViolations, rulesAdded; summaryOnly and maxResults as in the investigation toolsrules or patterns is reported as scope-mismatch and kept unless updateSnapshot: true; updateSnapshot: false compares without writingDetects when the core layer imports from the shared layer (architectural anti-pattern) with reverse dependency impact assessment.
Key features:
Discovers recurring patterns with self-learning capabilities.
Key features:
| Tool | Purpose | Cache | Time |
|---|---|---|---|
| collect-feedback | Store the outcome of a transformation or a corrected analysis result | no | <1s |
| review-feedback | Patterns, quality trends and warnings from stored feedback | no | varies |
| suggest-improvements | Rule adjustment suggestions from feedback patterns | no | varies |
Manually collect transformation feedback for AI learning with privacy-first design.
Key features:
<projectRoot>/.claude-feedback; a second, platform-wide store only when ANGULAR_MODERNIZER_PLATFORM_ROOT is setUsage:
{
"transformation": {
"ruleId": "standalone-migration-v1",
"targetFile": "/src/app/user.component.ts",
"approach": "Migrate to standalone component",
"reasoning": "Isolated component, no complex dependencies",
"confidence": 0.95
},
"execution": {
"succeeded": true,
"duration": 1200
},
"validation": {
"buildSuccess": true,
"testsPass": true
},
"storageLocation": "both" // 'project', 'platform', or 'both' (default)
}
Storage: feedback always goes to <projectRoot>/.claude-feedback/sessions/. both (default) adds the platform store only when ANGULAR_MODERNIZER_PLATFORM_ROOT is set; platform requires that variable and fails without it. The server never derives a platform location from its own install path (installed from npm that would be the workspace root or a node_modules / npx cache).
Returns:
feedbackId: unique identifier for this feedbacksessionId: session this feedback belongs tostored: boolean indicating successful storagestorageLocations: array of paths where feedback was savedvalidationResult: quality validation resultslearnings: extracted patterns and insightsOptional on failure: execution.errorType (build, type, lint, test, runtime, syntax, semantic, timeout, unknown; inferred from execution.error when omitted) and validation.buildErrors (string array, used as learning evidence).
Analysis records (kind: "analysis") report a read-only tool result that had to be corrected by grep, build output, a script or manual reading. No execution or build data is needed; analysis takes one record or an array:
{
"kind": "analysis",
"analysis": {
"tool": "find-usages",
"query": { "symbolName": "OrderListComponent" },
"claimed": "0 usages outside the declaring module",
"actual": "3 template usages in 2 .html files",
"fallbackUsed": "grep", // grep | build | script | manual | none | other
"evidence": ["git grep -n '<app-order-list' -- '*.html'"],
"impact": "high", // optional: low | medium | high
"category": "blind-spot" // optional: blind-spot | false-positive | false-negative | bug | missing-capability | config-drift
}
}
Returns kind, sessionId, stored, storageLocations and per-record records[] (feedbackId, stored, completenessScore, issues). review-feedback reports these records under analysisInsights.
Review collected feedback and extract actionable insights for AI learning.
Key features:
<projectRoot>/.claude-feedback, plus the platform store when ANGULAR_MODERNIZER_PLATFORM_ROOT is set (sourcesRead lists the folders)Usage:
{
"source": "both",
"analysisType": "all",
"minConfidence": 0.7,
"minCompleteness": 70,
"category": "standalone-migration",
"since": "2025-12-01"
}
Returns:
sessions: number of sessions reviewedtransformations: number of transformations analyzedsuccessRate: overall success rate (0.0-1.0)insights: array of detected patterns with confidence scoresqualityWarnings: warnings about low-quality feedbacksourcesRead: locations where feedback was read fromanalysisRecords, analysisInsights: number of analysis records and the insights drawn from themGenerate suggestions for transformation rules based on feedback patterns.
Key features:
requiresApproval: true)Suggestion types:
Usage:
{
"ruleId": "standalone-migration-v1",
"source": "both",
"minConfidence": 0.7
}
Returns:
ruleId: rule these suggestions apply tocurrentPerformance: successRate, avgDuration, qualityImprovement of the rulesuggestions: array of suggestions sorted by confidence (descending)feedbackCount: number of feedback records analyzedanalysisFeedbackCount: number of analysis records for this toolsourcesRead: locations where feedback was read fromExample suggestion:
{
"type": "parameter-adjustment",
"description": "Lower confidence threshold for this rule",
"reasoning": "3 failures occurred with high confidence (>0.8), suggesting overconfidence in predictions",
"confidence": 0.8,
"expectedImprovement": "Reduce false positives by 21%",
"implementation": "Adjust rule confidence threshold from 0.8 to 0.9. Review decision-making logic to improve accuracy.",
"requiresApproval": true
}
| Tool | Purpose | Cache | Time |
|---|---|---|---|
| plan-migration | Style-aware strategy generation; scan-based roadmap from file-level violations | ProjectCache | 1-3s |
| orchestrate-migration | Multi-step workflows with dependency management and checkpoint/resume | no | varies |
Generates comprehensive migration strategies based on violations, architecture, and codebase style.
Key features:
projectRoot and violations that carry filePath (inline or via scanResultFile, a
saved scan-architecture result) the phases list concrete files, grouped per file and layer, ordered dependencies
first along the import graph plus template edges (a host after the components, directives and pipes its
template uses), import cycles kept together (planSource: "scan", details in scanPlan;
maxPhases, summaryOnly, maxResults caps files per phase and violations per file, default 25)planSource: "template")summary names strategy, roadmap and scan plan as text; the scan-based plan adds warnings when library imports do not resolvescanResultFile also accepts a saved MCP result (structuredContent of scan-architecture or scan-all)| Tool | Purpose | Cache | Time |
|---|---|---|---|
| transform-code | 26 transformation types | no | varies |
| run-schematic | Angular schematic execution | no | varies |
| run-angular-cli | CLI command execution | no | varies |
| run-build | Multi-build system support | no | varies |
Applies surgical code transformations with pre-validation, backup, build validation, and automatic rollback.
26 transformation types:
plugin-angular transform rules run only for the requested type: transform-code passes transformationType and the call's options under the '@angular-modernizer/plugin-angular' config key.
Safety features (single file, batch and streaming alike):
<projectRoot>/.angular-modernizer-backups (backupDir overrides): a copy per file with a metadata file next to it, plus a git snapshot (git stash create, working tree and stash list untouched) inside a git repository (backup.gitSnapshot)validation.introducedTypeErrors)validateBuild), project lint only on request (validateLint)autoRollback)validation.introducedTypeErrors lists <file>: <error>), and applies rollbackStrategy (all-or-nothing, selective, none) to failed filesrollback-changes restores the same backups later (strategy: auto, file-backup, git-stash)Validation parameters:
validateBuild: boolean - run the project build after transformation (default: false; the transformed file is type-checked either way); buildValidation is reported only when it ranvalidateLint: boolean - run the project's lint script (default: false; it lints the whole project)buildTimeout: number - build timeout in ms (default: 300000 = 5 min)projectRoot: string - project root for backups and build executionBuild validation (validateBuild) runs build.command of .angular-modernizer.json, else the detected build system (npx ng build, npx nx build, npx vite build), else the build script of package.json; without one the build is skipped with a warning. A cancelled call restores the backup (see Progress and Cancellation).
Streaming (deprecated): streaming defaults to false. With streaming: true the call returns an operationId at once, runs the same path in the background and get-operation-progress returns the result. diffFormat has no effect.
unified: traditional git-style diff (human-readable, backward compatible)structured: machine-first JSON diff with semantic annotations (AI-optimized)both: include both formats (useful for debugging, higher overhead)Structured diff features:
Supported build systems: Angular CLI, Nx, Vite, Webpack, npm
| Tool | Purpose | Cache | Time |
|---|---|---|---|
| validate-before-transform | Pre-transformation checks | no | 1-2s |
| validate-transformation | Post-transformation checks | no | 30-300s |
| rollback-changes | Revert transformations | no | <1s |
| check-incremental-compatibility | Whether a project supports incremental build validation | no | varies |
| validate-project-compatibility | Parser compatibility before transformations | no | varies |
| analyze-build-impact | Changed files -> value, type-only and template dependents, affected modules, strategy | ProjectCache | ~1s warm |
| get-operation-progress | Deprecated: progress and result of a streaming operation | no | <1s |
filesToChange is the changed set. Dependents are split into value dependents (JS rebuild), type-only dependents
(type-check only) and template dependents: host components that use a changed component, directive or pipe only in
their template (NgModule declarations), listed with the used classes in templateHosts. Barrels only forward the
names they re-export; past the first importer only exports whose type surface (annotations, inferred types, heritage,
@NgModule exports) names a changed binding propagate, so using a class inside a method body or a decorator stops
there. symbols narrows the impact to consumers of given exports (symbolImpacts). .html files map
to their component (mappedFiles), which counts as changed without its dependents. summaryOnly / maxResults
shorten the lists; counts always describe the full result. summary repeats the recommendation and the counts as
text; warnings reports library imports that do not resolve, dependents can then be missing.
Read-only tools over the shared ProjectCache: a workspace is parsed once per server and re-read per changed file.
All list-heavy tools take summaryOnly and maxResults. All answer with structuredContent and a summary string.
When packages declared in the project's package.json do not resolve (no or incomplete node_modules), the tools that
load the program add warnings with the number of unresolved library imports: library types are then any and hosts,
callers and handlers can be missing from the result. The check runs once per loaded project (about 50 ms on 4000 files).
| Tool | Answers |
|---|---|
| parse-stack-trace | Structured frames from Node.js / Angular / Zone.js / browser stacks, browser URLs and bare file names mapped onto project files |
| find-usages | Every reference to a symbol, classified (declaration, read, write, call, template, unresolved) |
| get-call-graph | Callers and callees of a method or function, incl. template callers (own and inheriting subclass templates); maxNodes caps the tree |
| resolve-type | TypeScript type at file:line:col (nullable, async, generics, declaration) |
| find-angular-symbol | Components, directives, pipes, services, ... by selector, pipe name or class, incl. library classes from .d.ts |
| search-codebase | Text, regex or declaration search, incl. .html and files outside the program |
| list-imports | Imports and re-exports of a file with resolved targets (aliases, barrels); counts per kind |
| inspect-template | Template structure: elements, bindings, matched components/directives/pipes, control flow, i18n keys |
| find-component-hosts | Every template host of a component or directive with bound, unbound and missing required inputs/outputs; components created in code (dialogs, createComponent, routes) |
| trace-output-flow | Payload of an @Output across the template boundary and into subscriptions in code (ref.instance.x.subscribe), and dialog data in / results out |
| get-bootstrap-execution | What runs at startup (initializers, bootstrap, interceptors, provider factories) and where a watched expression is touched |
| inspect-form-group | Reactive Forms structure and every enable/disable/validator change per control |
| inspect-i18n | Translation keys: definitions per language and overlay, usages in templates and code, missing and undefined keys |
| verify-citations | Whether the path:line citations of Markdown plans still point at the named code: ok, unverified, moved (new lines), anchor-missing, out-of-range, missing-file (similar files), ambiguous |
| Tool | Purpose |
|---|---|
| server-status | server version, pid, uptime, memory, cached projects, response sizes, and whether the dist was rebuilt since start |
scan-all reads and writes only its own cache, .angular-modernizer-cache/all/. It does not read the caches written by scan-architecture, scan-solid and scan-angular. An earlier version did ("cross-cache reading"), but it opened them with its own cache version scan-all-2, so their entries never matched and were invalidated (deleted) on every scan-all run; a hit would also have returned only one plugin's findings. The individual scans keep writing and reading their own caches.
Cache statistics example (second run, nothing changed):
{
"hitRate": 100,
"hitsBySource": {
"all": 450
}
}
hitRate and hitsBySource refer to the own cache (all) only. hitRate is a percentage. The first run has 0%; later runs analyze only changed files.
Deprecated in 1.1:
parallelandincrementalof analyze-project and scan-architecture select the old WorkerPool path, which will be removed in 2.0. On a large app (371 files) it was no faster than the default path (10.8-12.1 vs 10.3-13.1 s), blocked the server for up to 10.7 s and took about four times the memory; before 1.1 the automatic mode selection could fail withNot implemented yet. The default path runs the analysis in a scan worker. Leave these options unset; the text below describes the old path.
The orchestration system automatically selects between Promise-based and worker thread parallelism based on project complexity score:
Score 0-35: Promise mode (small projects)
Score 35-50: Promise mode with monitoring
Score 50-75: Worker mode preferred
Score 75-100: Worker mode required
Performance results (1,500 files, 13 rules):
Memory management:
Configuration (enabled by default):
orchestration: {
autoSelectMode: true, // Default, no configuration needed
}
The learn-patterns tool persists discovered patterns across scans in .angular-modernizer-cache/pattern-knowledge.json. This enables pattern evolution tracking, confidence improvement over time, style shift detection, and pattern velocity measurement.
Example evolution output:
{
"scan1": { "patterns": 15, "avgConfidence": 0.65 },
"scan2": { "patterns": 18, "avgConfidence": 0.72 },
"scan3": { "patterns": 16, "avgConfidence": 0.78 },
"evolution": {
"newPatterns": 3,
"deprecatedPatterns": 2,
"confidenceImprovement": 0.13,
"patternStability": 0.85
}
}
Per-tool defaults go under tools in .angular-modernizer.json; arguments of a call override them. The schema lists
the configurable tools (scan-architecture, scan-all, scan-angular, scan-solid, analyze-project, transform-code,
transform-code-batch, run-build, validate-transformation, collect-feedback, review-feedback, suggest-improvements) and
their keys; orchestration takes a different set of keys per tool. Other tools, such as learn-patterns, take their
options per call only. analyze-project reads tools.analyze-project except orchestration: its parallel and
incremental select the deprecated WorkerPool path, which only the call argument can choose.
{
"build": {
"command": "ng build",
"mode": "incremental"
},
"tools": {
"analyze-project": {
"excludePatterns": ["**/node_modules/**", "**/dist/**"],
"maxResults": 1000
},
"scan-architecture": {
"maxFiles": 500,
"includeAutoFixes": true
},
"review-feedback": {
"source": "both",
"minConfidence": 0.7
}
}
}
The scan tools cache per file with these built-in settings (not configurable):
cacheConfig: {
enabled: true,
cacheDir: '.angular-modernizer-cache',
maxSize: 100 * 1024 * 1024, // 100MB
maxAge: 24 * 60 * 60 * 1000, // 24 hours
compression: true
}
Cache locations:
architecture: .angular-modernizer-cache/architecture/solid: .angular-modernizer-cache/solid/angular: .angular-modernizer-cache/angular/all (scan-all): .angular-modernizer-cache/all/patterns: .angular-modernizer-cache/pattern-knowledge.jsonWhen to clear cache:
rm -rf .angular-modernizer-cache
Deprecated in 1.1:
parallelandincrementalof analyze-project and scan-architecture select the old WorkerPool path, which will be removed in 2.0. On a large app (371 files) it was no faster than the default path (10.8-12.1 vs 10.3-13.1 s), blocked the server for up to 10.7 s and took about four times the memory; before 1.1 the automatic mode selection could fail withNot implemented yet. The default path runs the analysis in a scan worker. Leave these options unset; the text below describes the old path.
For large projects (500+ files), in tools.scan-architecture (or per call as the orchestration argument):
{
"orchestration": {
"parallel": true,
"autoSelectMode": true,
"enableProgress": true,
"enableMonitoring": true,
"resourceLimits": {
"maxMemory": 4294967296,
"maxWorkers": 8
}
}
}
For small projects (<100 files):
{
"orchestration": {
"parallel": false,
"autoSelectMode": true
}
}
1. analyze-project
(framework, architecture, layers)
2. scan-architecture
(violations by category)
3. learn-patterns
(codebase style profile)
4. plan-migration
(style-aware strategy)
1. validate-before-transform
(check syntax, types, dependencies)
2. transform-code (with safety flags)
(backup -> transform -> validate)
3. validate-transformation
(build, lint, tests)
4. rollback-changes (if needed)
Day 1: Full scan + cache write
Day 2+: Incremental scan (changed files only)
Weekly: Full scan + pattern evolution check
Each scan tool keeps its own cache, so repeated runs of the same tool are fast. scan-all does not reuse the individual caches; run either the individual scans or scan-all, not both, for a full picture:
# Individual scans (write plugin-specific caches)
scan-architecture # Writes: .cache/architecture/
scan-solid # Writes: .cache/solid/
scan-angular # Writes: .cache/angular/
# Combined scan: own cache only, does not read the caches above
scan-all # Writes and reads: .cache/all/
Second run performance:
Always use safety features:
transform-code: {
validateBeforeTransform: true,
createBackup: true,
validateTransformation: true,
autoRollback: true
}
Batch transformations:
{
files: [...],
rollbackStrategy: "all-or-nothing"
}
Long-running tools report progress through MCP notifications/progress when the request carries _meta.progressToken, and stop when the client sends notifications/cancelled (Esc in Claude Code). Without a token no progress notification is sent. Notifications are throttled: the first and the last value, at most one per 250 ms.
| Tool | Progress | On cancel |
|---|---|---|
| scan-architecture, scan-all, scan-solid, scan-angular, analyze-project | files (n/N files, v violations); worker paths of analyze-project forward the kernel progress, batched scan-architecture reports per batch |
stops between files |
| compare-health | through scan-all | no comparison, snapshot not written |
| transform-code | single file: 3 steps (loaded, transformed, validated); batch: files | restores the backup (also with autoRollback: false); a batch restores every file |
| run-build, run-angular-cli, run-schematic, validate-transformation | none | ends the build with its process tree (SIGTERM, SIGKILL after 5 s) |
| orchestrate-migration | steps | passes the cancel to the running step, runs no further step |
| find-usages, get-call-graph, resolve-type, find-angular-symbol, search-codebase, list-imports, inspect-template, find-component-hosts, trace-output-flow, get-bootstrap-execution, inspect-form-group, inspect-i18n, analyze-build-impact, plan-migration | first call on a workspace: files loaded (n/N files loaded, per batch of 50) |
stops the project load at the next batch, nothing is cached; program and checker build and the query are not interrupted |
A cancelled request gets no response (MCP spec). Scans also stop while they add their files to the project (checked per file). Only the kernel's own project load (kernel.initialize()) and transform-code's load of its file cannot be interrupted; the cancel takes effect right after them. Direct callers of a scan get the analyzed part with execution.stopReason: 'cancelled'.
streaming: true (transform-code, scan-architecture) and get-operation-progress stay in 1.x but are deprecated; streaming defaults to false. With streaming: true the call returns an operationId at once and runs in the background: transform-code runs its regular path (same backup, validation and rollback) and emits no events, scan-architecture emits phase events (0, 10, 20, 30 %, every 10 files up to 90 %, 100 % on completion). get-operation-progress returns status, the events and, once completed, the tool result in result. Operations expire 5 minutes after they end (10 minutes when stuck running). There is no way to cancel a streaming operation over MCP; call the tools synchronously instead.
Cause: memory or worker limit exceeded.
Solutions:
maxFiles: 50autoSelectMode: trueresourceLimits.maxMemory: 4GBmaxWorkers: 2Yes, this is normal for the first run.
hitRate: 0% means the tool's own cache is empty (for scan-all: .angular-modernizer-cache/all/)scan-all does not read the caches of the individual scans, so running them first does not raise its hit ratehitRate > 0%Cause: worker script not compiled or unavailable.
Solutions:
pnpm builduseWorkerThreads: falseautoSelectMode: true (auto-detects and uses Promises)Cause: code has existing syntax/type errors.
Solutions:
preValidation.issues arrayvalidateBeforeTransform: true (default)Cause: large project analyzed without batching.
Solutions:
maxFiles: 100 (batching enabled)enableMonitoring: trueresourceLimits.maxMemoryrm -rf .angular-modernizer-cache| Project Size | Files | analyze-project | scan-architecture | learn-patterns |
|---|---|---|---|---|
| Small | <100 | 2-3s | 5-10s (cache: 1s) | 10-20s |
| Medium | 100-500 | 5-10s | 15-30s (cache: 3s) | 20-40s |
| Large | 500-1500 | 10-20s | 60-120s (cache: 5s) | 40-90s |
| Enterprise | 1500+ | 20-40s | 180-300s (cache: 10s) | 90-180s |
Cache timings apply to the second run with full cache hit.
| Configuration | Peak Memory | Recommended RAM |
|---|---|---|
| Sequential | ~800MB | 2GB |
| Promise (4 workers) | ~1.2GB | 4GB |
| Worker (4 workers) | ~3.2GB | 8GB |
| Auto-selection | ~1.5GB | 4GB |
Memory calculation:
src/tools/README.mdMIT License - See LICENSE file for details
MCP server of the Angular Modernizer: 41 tools for analysis, migration planning, transformation, build validation, rollback, feedback and bug investigation of Angular projects, served over stdio with the MCP TypeScript SDK.
Remarks
The server speaks both protocol eras on one stdio connection: clients that open with
initializeget the revision they ask for (2025-06-18, 2025-11-25), clients that open withserver/discoverget 2026-07-28. Arguments are validated against each tool's input schema; every tool answers withstructuredContentvalidated against its output schema and a text block with the result'ssummary.Run the server through the
angular-modernizer-mcpbin (dist/cli.js):cli.jstakes--max-projects Nand--max-heap-mb Nfor the shared ts-morph project cache (defaults 3 and 2048 MB, 0 = no heap limit).The package entry exports the building blocks for embedding the server or calling tools directly:
start().ANGULAR_MODERNIZER_DEBUG.Example