# angular-signal-forms-migration-mcp [Health: Active]

**Category:** 💻 Developer Tools  
**Repository:** https://github.com/Alvi97/angular-signal-forms-migration-mcp  
**GitHub Stars:** 0  
**npm Downloads (last month):** 638  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/angular-signal-forms-migration-mcp

## Description
Finds Angular Reactive Forms and returns verified Signal Forms recipes. Never edits code.

## Tools
Capabilities this server exposes over MCP:

- **find_form_candidates** — Where are the Reactive Forms constructs, and which need a person?
- **get_signalforms_recipe** — What is the verified before→after for this construct?
- **analyze_migration_complexity** — How big is this job, and which file should I start with?
- **get_migration_report** — Give me the whole thing as one markdown document.
- **verify_migration** — I already migrated this — what compiles but is still wrong?
- **get_angular_upgrade_plan** — I am below v21. How do I get to a version that supports this?

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `npx` (confidence: high):

```json
"mcpServers": {
  "angular-signal-forms-migration-mcp": {
    "command": "npx",
    "args": ["-y","angular-signal-forms-migration-mcp@latest"]
  }
}
```

## Documentation & README

# angular-signal-forms-migration-mcp

[![npm](https://img.shields.io/npm/v/angular-signal-forms-migration-mcp.svg)](https://www.npmjs.com/package/angular-signal-forms-migration-mcp)
[![node](https://img.shields.io/node/v/angular-signal-forms-migration-mcp.svg)](https://nodejs.org)
[![license](https://img.shields.io/npm/l/angular-signal-forms-migration-mcp.svg)](./LICENSE)

An MCP server that helps an AI coding agent migrate **Angular Reactive Forms** to
**Angular Signal Forms**.

It finds the Reactive Forms constructs in your codebase, separates the safe mechanical
renames from the ones that need a human decision, and hands back before→after recipes
that are verified against a real Angular release rather than written from memory.

## Install

Requires Node.js 20+. Nothing to clone — `npx` fetches it on demand.

```bash
claude mcp add signal-forms-migration -- npx -y angular-signal-forms-migration-mcp@latest
```

Or add it to any MCP client config:

```json
{
  "mcpServers": {
    "signal-forms-migration": {
      "command": "npx",
      "args": ["-y", "angular-signal-forms-migration-mcp@latest"]
    }
  }
}
```

`@latest` makes `npx` re-resolve on every launch, so restarting your editor picks up new
releases. Without it, npx keeps serving whichever version it cached first — repoint the
config at `@latest`, or clear the cache with `npm cache clean --force`.

The server also checks for a newer version once a day and writes a one-line notice to
**stderr**. It is throttled, times out after 2 seconds, never touches stdout, and stays
silent on any failure. To turn it off, add
`"env": { "SIGNAL_FORMS_MCP_NO_UPDATE_CHECK": "1" }` to the config block above. To see what
is actually running:

```bash
npx angular-signal-forms-migration-mcp@latest --version
```

> [!IMPORTANT]
> **Do not `npm install` this into your Angular app.** It is a standalone process your
> editor spawns, not a library your project depends on. `npx` keeps it in a cache outside
> your project entirely.

> [!NOTE]
> **It detects and advises. It never edits your code.** There is no tool here that writes
> to your source files, and there never will be. The server returns findings and recipes;
> your agent decides what to change and makes the edits, so every change still goes
> through your normal review and version control.

## What it looks like

```
> Migrate the forms in src/app/checkout to Signal Forms.

  1. find_form_candidates { path: ".../src/app/checkout" }
     → 9 findings across 2 files: 6 mechanical, 3 judgment
       (the FormArray of line items is judgment — its shape changes)
  2. get_signalforms_recipe { construct: "FormBuilder.group" }
     → before/after + caveats
  3. the agent applies the edits, you review the diff
  4. verify_migration { path: ".../checkout.component.ts" }
     → traps that compile and are still wrong
```

## Prerequisites it checks before advising anything

A migration report leads with the things that make migration impossible, because a plan
you cannot execute is worse than no plan:

1. **Angular 21+.** `@angular/forms/signals` does not exist before v21. Below that the
   server returns an upgrade plan instead of a migration plan.
2. **Declared and installed versions agree.** An old branch checked out over newer
   `node_modules` straddles the v21 line. Migrating against what is installed means the
   next `npm ci` reverts you to a version where the target API is absent — so the server
   refuses to pick a side and says so.
3. **`moduleResolution` is exports-aware** (`bundler`, `node16`, or `nodenext`).
   `@angular/forms/signals` is a package-exports subpath; legacy `node` resolution cannot
   see it, and the import fails with an error that looks like a missing dependency.

## Tools

| Tool                           | What it answers                                                   |
| ------------------------------ | ----------------------------------------------------------------- |
| `find_form_candidates`         | Where are the Reactive Forms constructs, and which need a person? |
| `get_signalforms_recipe`       | What is the verified before→after for this construct?             |
| `analyze_migration_complexity` | How big is this job, and which file should I start with?          |
| `get_migration_report`         | Give me the whole thing as one markdown document.                 |
| `verify_migration`             | I already migrated this — what compiles but is still wrong?       |
| `get_angular_upgrade_plan`     | I am below v21. How do I get to a version that supports this?     |

Full parameters, response shapes and scope limits: **[docs/TOOLS.md](https://github.com/Alvi97/angular-signal-forms-migration-mcp/blob/HEAD/docs/TOOLS.md)**.

## How the recipes are verified

Signal Forms is new and is not reliably present in any model's training data — recipes
written from memory are wrong in ways that look right. So none of these are.

Recipes are verified against **Angular v22** using the official Angular CLI MCP server,
cross-checked against angular.dev, and carry structured provenance
(`verifiedAgainstVersion`, `retrievedISO`, `sources`) that ships in the tool response so
your agent can judge how current the advice is. A recipe with an empty `sources` list
fails CI.

Where the docs do not answer the question, the recipe **says so in its caveats** rather
than inventing an answer — `UNVERIFIED — confirm on <url>`, or `UNVERIFIED — tool-authored
guidance` where Angular documents no migration path at all (the RxJS stream tiers are the
main case: the primitives are documented and compile, but choosing between them is this
tool's judgement, not Angular's). **14 of 37 recipes** currently carry such a marker. That
is the honest part of the output, not an oversight — and a test keeps this number true.

**The recipes also compile.** CI installs a real `@angular/forms@22` and typechecks
fixtures exercising every API the recipes use, so a recipe naming a function that does not
exist — or calling it with the wrong argument shape — fails the build. That is what
established `disabled(path, { when })` as the v22 signature; the docs demonstrate neither
it nor the nested `schema()` + `apply()` composition.

Two things this caught that memory gets wrong:

- The binding directive is `[formField]` / `FormField` — **not** `[control]` / `Control`,
  which appeared in pre-release v21 material and is what models reproduce.
- `disabled()` / `hidden()` gained an options-object form on v22 and marked the bare
  callback `@deprecated` rather than removing it — so a v21-shaped rule still compiles,
  with a warning. Established by diffing the shipped overloads, not the guides.

Recipes whose behaviour genuinely differs across releases carry a `VERSION-SENSITIVE`
caveat naming the form each version takes, and the server resolves them against your
project's detected version. **Read the `caveats` array** — that is where the sharp edges
live.

The re-verification procedure for a new Angular release is
[REVERIFICATION.md](https://github.com/Alvi97/angular-signal-forms-migration-mcp/blob/HEAD/REVERIFICATION.md).

## It tells you when there is no clean answer

Not every Reactive Forms pattern has a Signal Forms equivalent, and a migration tool that
pretends otherwise is worse than none. Form streams are graded by the RxJS operators in
their `.pipe()` chain:

| Tier     | Operators                                                     | Answer                                             |
| -------- | ------------------------------------------------------------- | -------------------------------------------------- |
| trivial  | none / bare `subscribe`                                       | `computed()`, or `effect()` for a real side effect |
| moderate | `map`, `filter`, `debounceTime`, `distinctUntilChanged`, …    | `computed()` + the `debounce()` schema rule        |
| hard     | `switchMap`, `combineLatest`, `withLatestFrom`, `forkJoin`, … | **no direct equivalent**                           |

For the hard tier the recipe says so outright and offers three real strategies — async
validation rules, `rxResource`, or keeping RxJS behind `toObservable`/`toSignal` — rather
than inventing a one-liner that does not exist.

Likewise `addControl()` / `removeControl()` have no counterpart at all: the field tree is
derived from the model signal's type. The recipe explains the three actual answers instead
of implying an API that would not compile.

## What it will not do

- **Edit your files.** By design, permanently.
- **Prove your migration is correct.** `verify_migration` proves the absence of _known_
  defects. Run it after `tsc`, not instead of it.
- **Migrate template-driven forms.** `ngModel` migration is undocumented upstream;
  guessing it would be the exact failure mode this project exists to avoid.
- **Read template literals with `${...}` substitutions**, because their text is not what
  the Angular compiler sees. Inline `template:` strings without substitutions _are_
  scanned.
- **Scan CSS/SCSS**, or resolve types across files — detection is a single-file syntactic
  pass, not a `ts.Program`.

[ROADMAP.md](https://github.com/Alvi97/angular-signal-forms-migration-mcp/blob/HEAD/ROADMAP.md) tracks these; the migration report repeats them in its own
"Scope" section rather than letting the totals imply completeness.

## Why not just the official Angular MCP server?

Use both. The official `@angular/cli` MCP server knows about _Angular_; this one knows
about _migration_ — which constructs exist in your code, which are mechanical, which need
a decision, and what the verified replacement is. Your agent can pull findings and recipes
from here, then confirm anything current or project-specific there before it edits.

## Status

Feature-complete through M16. Six tools ship, with doc-verified recipes covering basic
constructs, arrays, runtime shape mutation, async validators, custom controls, the three
RxJS stream tiers, reading and writing form state, submission, model-shape constraints,
CSS status classes, spec-file migration, and the `.html` template layer — bindings, state
reads, the `<select multiple>` blocker, and the silent error-key rename.

The transport is stdio, so stdout is reserved for the protocol and all logging goes to
stderr.

Contributions and local development: [CONTRIBUTING.md](https://github.com/Alvi97/angular-signal-forms-migration-mcp/blob/HEAD/CONTRIBUTING.md).

## License

MIT

