-
Notifications
You must be signed in to change notification settings - Fork 8
feat(ng-schematics): add MCP server integration for AI assistant support #1606
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| { | ||
| "builders": { | ||
| "mcp": { | ||
| "implementation": "./builders/mcp/index", | ||
| "schema": "./builders/mcp/schema.json", | ||
| "description": "Starts the Ignite UI MCP server for AI assistant integration" | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| import * as fs from "fs"; | ||
| import * as path from "path"; | ||
| import { spawnSync } from "child_process"; | ||
| import { createBuilder, BuilderContext, BuilderOutput } from "@angular-devkit/architect"; | ||
| import { McpOptions } from "../../mcp/schema"; | ||
|
|
||
| export default createBuilder<McpOptions>((options: McpOptions, context: BuilderContext): BuilderOutput => { | ||
| let mcpEntry: string; | ||
| try { | ||
| const mcpPkgJson = require.resolve("@igniteui/mcp-server/package.json"); | ||
| mcpEntry = path.resolve(path.dirname(mcpPkgJson), "dist", "index.js"); | ||
| } catch { | ||
| context.logger.error( | ||
| "MCP server package not found. Install it first:\n" + | ||
| " yarn install\n" | ||
| ); | ||
| return { success: false }; | ||
|
Comment on lines
+10
to
+17
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you make the MCP a dep of the schematics package it'll always be there and you can directly import from it, if that suits us better. |
||
| } | ||
|
|
||
| if (!fs.existsSync(mcpEntry)) { | ||
| context.logger.error( | ||
| "MCP server not built. Build it first:\n" + | ||
| " npm run build:mcp\n" | ||
| ); | ||
| return { success: false }; | ||
| } | ||
|
Comment on lines
+20
to
+26
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Surely, if that's user project context working with shipped packages they wouldn't need to build anything additionally themselves, right? |
||
|
|
||
| const args: string[] = []; | ||
| if (options.remote) { | ||
| args.push("--remote", options.remote); | ||
| } | ||
| if (options.debug) { | ||
| args.push("--debug"); | ||
| } | ||
|
|
||
| spawnSync(process.execPath, [mcpEntry, ...args], { stdio: "inherit" }); | ||
| return { success: true }; | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| { | ||
| "$schema": "http://json-schema.org/draft-07/schema", | ||
| "type": "object", | ||
| "properties": { | ||
| "remote": { | ||
| "type": "string", | ||
| "description": "Backend URL for remote mode (uses HTTP instead of local SQLite)" | ||
| }, | ||
| "debug": { | ||
| "type": "boolean", | ||
| "description": "Enable debug logging to mcp-server.log", | ||
| "default": false | ||
| } | ||
| } | ||
| } |
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one is a duplicate of packages/ng-schematics/src/builders/mcp/index.ts (or the other way around) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| import * as fs from "fs"; | ||
| import * as path from "path"; | ||
| import { spawnSync } from "child_process"; | ||
| import { Rule, SchematicContext, Tree } from "@angular-devkit/schematics"; | ||
| import { defer } from "rxjs"; | ||
| import { McpOptions } from "./schema"; | ||
|
|
||
| export default function(options: McpOptions): Rule { | ||
| return (_tree: Tree, _context: SchematicContext) => { | ||
| return defer(async () => { | ||
| let mcpEntry: string; | ||
| try { | ||
| const mcpPkgJson = require.resolve("@igniteui/mcp-server/package.json"); | ||
| mcpEntry = path.resolve(path.dirname(mcpPkgJson), "dist", "index.js"); | ||
| } catch { | ||
| _context.logger.error( | ||
| "MCP server package not found. Install it first:\n" + | ||
| " yarn install\n" | ||
| ); | ||
| return _tree; | ||
| } | ||
|
|
||
| if (!fs.existsSync(mcpEntry)) { | ||
| _context.logger.error( | ||
| "MCP server not built. Build it first:\n" + | ||
| " npm run build:mcp\n" | ||
| ); | ||
| return _tree; | ||
| } | ||
|
|
||
| const args: string[] = []; | ||
| if (options.remote) { | ||
| args.push("--remote", options.remote); | ||
| } | ||
| if (options.debug) { | ||
| args.push("--debug"); | ||
| } | ||
|
|
||
| spawnSync(process.execPath, [mcpEntry, ...args], { stdio: "inherit" }); | ||
| return _tree; | ||
| }); | ||
| }; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| { | ||
| "$schema": "http://json-schema.org/draft-07/schema", | ||
| "type": "object", | ||
| "properties": { | ||
| "remote": { | ||
| "type": "string", | ||
| "description": "Backend URL for remote mode (uses HTTP instead of local SQLite)", | ||
| "alias": "r" | ||
| }, | ||
| "debug": { | ||
| "type": "boolean", | ||
| "description": "Enable debug logging to mcp-server.log", | ||
| "default": false, | ||
| "alias": "d" | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| export interface McpOptions { | ||
| remote?: string; | ||
| debug?: boolean; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get
ng gis odd for a schematic integration that's not meant to actually generate any code (sadly that's the equivalent exposed throughngof the generic Schematics CLI), but having it as a builder isn't less awkward TBH.The MCP is also not a builder and isn't associated with any project's build pipeline, so calling
ng run client-app:mcpfor example is off for me, especially if there are multiple projects in the workspace.Also, not sure how starting the MCP server that way would be useful - I don't see any modification of the
mcp.jsonand I'm not sure agents can discover and use the server like that to begin with.This could also be just a
binscript on either the schematics or the mcp package - depending on how you want it exposed and if the MCP is dep of the schematics or added as root dependency; basically ending up with identical integration asigniteui-clijust calling a different package in the config.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also consider some vendor prefix for the name like at least
ig-mcpif this remains as a builder,mcpalone is too generic.