You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
perf(cli): start the MCP server in-process before the CLI loads - #1871
ig mcp loaded the whole CLI before it reached the mcp command (yargs, every command, the template catalog of every framework) and then spawned node dist/index.js as a child, staying alive as its parent for the whole session. This cost about 0.7 s per start and an extra Node process (about 50 MB) per MCP session. It also made the server depend on the CLI's own start-up, e.g. every ig command crashed in a folder whose package.json has no dependencies field (#1870 fixes that crash; with this PR, ig mcp no longer runs that code at all).
bin/execute.js now handles ig mcp before the CLI loads: it picks the CLI copy as before (the project's local copy if there is one), finds @igniteui/mcp-server installed with that copy and imports it in the same process. The session runs in a single Node process, with no CLI parent and no child.
--remote <url>, --remote=<url> and --debug are passed to the server. --help, --version, any other or incomplete option (e.g. --debug=true, --no-debug), and a missing or unbuilt server fall back to the existing ig mcp command, so its help and error messages are unchanged. That fallback still loads the CLI and starts the server as a child process; the entries ig ai-config writes and the documented options never reach it.
The server lookup follows the CLI copy's real path, so the fast path also works in pnpm projects, where packages are linked and their dependencies sit next to the link target.
The "Different igniteui-cli global and local version" notice now goes to stderr. On stdout it would reach the MCP client as an invalid protocol message.
Warm start to the initialize response (Windows, Node 24): 1.04–1.13 s before, 0.42–0.49 s after; the server started directly takes 0.36–0.41 s.
Addresses the issue's second point (ig mcp loads the CLI and keeps it alive as the parent of the server process). #1870 handles the first: the entry ig ai-config writes. Projects that list igniteui-cli keep the npx -y igniteui-cli mcp entry, and this PR makes that path about as fast as starting @igniteui/mcp-server directly. npx runs the project's own CLI copy there, so these projects get the speed-up once they update igniteui-cli to a release that includes it.
#1870 and this PR touch different files and can merge in either order.
Type of Change
Bug fix (non-breaking change that fixes an issue)
New feature (non-breaking change that adds functionality)
Breaking change (fix or feature that would cause existing functionality to change)
I have built the project successfully (npm run build)
I have run the linter (npm run lint)
I have added/updated tests as needed
My changes do not introduce new warnings or errors
Additional Context
New tests:
Unit tests for the argument mapping and the server lookup.
Acceptance tests that run bin/execute.js mcp and check that the server answers initialize, that stdout carries only JSON-RPC, and that the process exits when stdin closes.
Acceptance tests for both --remote=<url> and --remote <url>: they call list_components against a local HTTP backend and check that the backend receives the request and its response reaches the tool result. They fail if the launcher drops the flag.
Each acceptance run has a deadline: a hung server is killed and the spec fails with the request it didn't answer.
`ig mcp` loaded the whole CLI (yargs, every template) and then spawned
the server as a second Node process. bin/execute.js now finds the
server installed with the selected CLI copy and imports it directly,
which halves the warm start (about 1.1 s to 0.45 s) and runs one
process per session. Help, version, other options and a missing or
unbuilt server still go through the CLI.
The server lookup follows the CLI copy's real path, so it works in
pnpm projects. The global/local version notice now goes to stderr, as
stdout carries the MCP protocol.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
The acceptance test lacks an internal deadline to kill the child and reject, so an unresponsive MCP server can leave its process and pipes alive after Jasmine times out.
Speeds up ig mcp by starting the MCP server in-process before loading the full CLI. This complements #1870 for projects that retain the local CLI entry.
Changes:
Adds an early MCP startup path using the selected CLI copy’s server, including pnpm-aware resolution.
Maps supported server arguments, preserves CLI fallback behavior, and sends version notices to stderr.
Adds unit and acceptance coverage for argument handling, server resolution, initialization, shutdown, and help.
File
Description
spec/unit/mcp-cli-spec.ts
Tests argument mapping and server entry resolution.
spec/acceptance/mcp-spec.ts
Tests initialization, protocol output, shutdown, and remote arguments.
spec/acceptance/help-spec.ts
Checks MCP command help output.
packages/cli/lib/commands/mcp.ts
Adds lightweight argument and server-resolution helpers.
packages/cli/bin/execute.js
Starts MCP before loading the CLI and routes version notices to stderr.
The spec now has its own deadline, shorter than the Jasmine timeout,
that kills the child and rejects, so a server that never answers
initialize or never exits doesn't outlive the spec.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
The acceptance test can pass even if --remote is dropped because initialization never contacts the remote backend, so it needs a fixture-backed tool call to verify argument forwarding.
No open issues 🎉
1 previously missed issue
In code that hasn't changed since last review
Test that remote mode forwards requests to the backend
spec/acceptance/mcp-spec.ts:80
This spec also passes if the launcher drops --remote entirely: both local and remote modes return the same serverInfo.name, and initialization never contacts the remote backend. Please call a remote-backed tool against a small HTTP fixture and assert that the fixture receives the request, so the acceptance test actually detects failures in the new argument-forwarding path.
The remote specs started the server against an unreachable URL and
only checked the initialize reply, which local mode returns too.
They now call list_components against a local HTTP fixture and
assert that the fixture received the request and that its response
reaches the tool result, for both --remote=<url> and --remote <url>.
The acceptance test can pass even if --remote is dropped because initialization never contacts the remote backend, so it needs a fixture-backed tool call to verify argument forwarding.
No open issues 🎉
1 previously missed issue
In code that hasn't changed since last review
Test that remote mode forwards requests to the backend spec/acceptance/mcp-spec.ts:80
This spec also passes if the launcher drops --remote entirely: both local and remote modes return the same serverInfo.name, and initialization never contacts the remote backend. Please call a remote-backed tool against a small HTTP fixture and assert that the fixture receives the request, so the acceptance test actually detects failures in the new argument-forwarding path.
Addressed: the remote specs now start a local HTTP fixture, call list_components through ig mcp --remote=<url> and --remote <url>, and assert that the fixture received GET /api/docs?framework=angular&filter=grid and that its response reaches the tool result. Verified that both specs fail when the flag is not passed (the request is then served from the local database).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
ig mcploaded the whole CLI before it reached themcpcommand (yargs, every command, the template catalog of every framework) and then spawnednode dist/index.jsas a child, staying alive as its parent for the whole session. This cost about 0.7 s per start and an extra Node process (about 50 MB) per MCP session. It also made the server depend on the CLI's own start-up, e.g. everyigcommand crashed in a folder whosepackage.jsonhas nodependenciesfield (#1870 fixes that crash; with this PR,ig mcpno longer runs that code at all).bin/execute.jsnow handlesig mcpbefore the CLI loads: it picks the CLI copy as before (the project's local copy if there is one), finds@igniteui/mcp-serverinstalled with that copy and imports it in the same process. The session runs in a single Node process, with no CLI parent and no child.--remote <url>,--remote=<url>and--debugare passed to the server.--help,--version, any other or incomplete option (e.g.--debug=true,--no-debug), and a missing or unbuilt server fall back to the existingig mcpcommand, so its help and error messages are unchanged. That fallback still loads the CLI and starts the server as a child process; the entriesig ai-configwrites and the documented options never reach it.Warm start to the
initializeresponse (Windows, Node 24): 1.04–1.13 s before, 0.42–0.49 s after; the server started directly takes 0.36–0.41 s.Related Issue
Closes #1864
Addresses the issue's second point (
ig mcploads the CLI and keeps it alive as the parent of the server process). #1870 handles the first: the entryig ai-configwrites. Projects that listigniteui-clikeep thenpx -y igniteui-cli mcpentry, and this PR makes that path about as fast as starting@igniteui/mcp-serverdirectly. npx runs the project's own CLI copy there, so these projects get the speed-up once they updateigniteui-clito a release that includes it.#1870 and this PR touch different files and can merge in either order.
Type of Change
Affected Packages
igniteui-cli(packages/cli)@igniteui/cli-core(packages/core)@igniteui/angular-templates(packages/igx-templates)@igniteui/angular-schematics(packages/ng-schematics)@igniteui/mcp-server(packages/igniteui-mcp)Checklist
npm run test)npm run build)npm run lint)Additional Context
New tests:
bin/execute.js mcpand check that the server answersinitialize, that stdout carries only JSON-RPC, and that the process exits when stdin closes.--remote=<url>and--remote <url>: they calllist_componentsagainst a local HTTP backend and check that the backend receives the request and its response reaches the tool result. They fail if the launcher drops the flag.