create-nudge-ui 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -6
- package/dist/agent-setup.d.ts +11 -7
- package/dist/agent-setup.js +55 -35
- package/dist/agent-verification.d.ts +3 -0
- package/dist/agent-verification.js +21 -0
- package/dist/arguments.d.ts +2 -1
- package/dist/arguments.js +8 -2
- package/dist/cli.d.ts +3 -1
- package/dist/cli.js +42 -9
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
`create-nudge-ui` detects an application's host framework, installs the
|
|
4
4
|
corresponding Nudge UI adapter, and updates the host configuration. The guided
|
|
5
|
-
setup can also connect a coding agent to
|
|
5
|
+
setup can also connect a coding agent to Nudge.
|
|
6
6
|
|
|
7
7
|
Run the initializer from the application root:
|
|
8
8
|
|
|
@@ -16,12 +16,13 @@ with React islands receives `nudge-ui/astro`, not `nudge-ui/vite`.
|
|
|
16
16
|
|
|
17
17
|
In an interactive terminal, the initializer asks whether to connect a coding
|
|
18
18
|
agent. It detects installed agents, installs the matching `@nudge-ui/mcp`
|
|
19
|
-
version in the project, and
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
version in the project, and installs a versioned reusable adapter under
|
|
20
|
+
`~/.nudge-ui/adapters/`. The adapter is independent of the application and
|
|
21
|
+
does not contain a project path, so different Git worktrees can use the same
|
|
22
|
+
global MCP registration. Existing project-scoped Nudge entries are backed up
|
|
23
|
+
and removed when the host supports that migration.
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
Fully restart the agent host, then ask it to “listen to Nudge.”
|
|
25
26
|
|
|
26
27
|
Use an explicit framework when automatic detection is ambiguous:
|
|
27
28
|
|
|
@@ -53,6 +54,13 @@ framework configuration:
|
|
|
53
54
|
npm create nudge-ui@latest -- --agent-only --agent codex --yes
|
|
54
55
|
```
|
|
55
56
|
|
|
57
|
+
For local MCP package testing, pass a tarball with `--mcp-package`. Setup uses
|
|
58
|
+
that artifact for both the project bridge and reusable adapter:
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
npx nudge-ui agent setup --mcp-package /absolute/path/to/nudge-ui-mcp.tgz
|
|
62
|
+
```
|
|
63
|
+
|
|
56
64
|
Agent configuration is best-effort. If an agent is not supported or its native
|
|
57
65
|
configuration cannot be updated, the initializer prints the complete stdio
|
|
58
66
|
configuration to add to that agent's project settings. Other MCP servers and
|
package/dist/agent-setup.d.ts
CHANGED
|
@@ -6,25 +6,29 @@ export interface AgentSetupPlan {
|
|
|
6
6
|
readonly projectRoot: string;
|
|
7
7
|
readonly packageSpecifier: string;
|
|
8
8
|
readonly installCommand: InstallCommand;
|
|
9
|
+
readonly adapterRoot: string;
|
|
10
|
+
readonly adapterInstallCommand: InstallCommand;
|
|
9
11
|
readonly serverConfig: McpServerConfig;
|
|
10
|
-
readonly serverEntry
|
|
12
|
+
readonly serverEntry: string;
|
|
11
13
|
}
|
|
12
14
|
export interface AgentInstallOutcome {
|
|
13
15
|
readonly agent: string;
|
|
14
16
|
readonly displayName: string;
|
|
15
17
|
readonly result?: InstallResult;
|
|
16
18
|
readonly unsupported: boolean;
|
|
19
|
+
readonly migrationError?: string;
|
|
20
|
+
readonly backups?: readonly string[];
|
|
17
21
|
}
|
|
18
|
-
/**
|
|
19
|
-
export declare function planAgentSetup(projectRoot: string, packageManager: PackageManager, nudgeUiVersion?: string): AgentSetupPlan;
|
|
22
|
+
/** Plans the project bridge dependency and an independent, versioned adapter installation. */
|
|
23
|
+
export declare function planAgentSetup(projectRoot: string, packageManager: PackageManager, nudgeUiVersion?: string, adapterDirectory?: string, mcpPackageSpecifier?: string): AgentSetupPlan;
|
|
20
24
|
/** Checks that a node_modules based install produced the configured executable. */
|
|
21
25
|
export declare function isAgentServerAvailable(plan: AgentSetupPlan): boolean;
|
|
22
|
-
/** Returns agents that
|
|
26
|
+
/** Returns agents that support a reusable stdio MCP configuration. */
|
|
23
27
|
export declare function projectAgentTypes(): AgentType[];
|
|
24
|
-
/** Detects installed or already configured agents
|
|
28
|
+
/** Detects installed or already configured agents. */
|
|
25
29
|
export declare function detectProjectAgentCandidates(projectRoot: string): Promise<AgentType[]>;
|
|
26
|
-
/**
|
|
27
|
-
export declare function configureProjectAgents(plan: AgentSetupPlan, selectedAgents: readonly string[]): AgentInstallOutcome[]
|
|
30
|
+
/** Registers the reusable adapter and removes the current project's overriding entry. */
|
|
31
|
+
export declare function configureProjectAgents(plan: AgentSetupPlan, selectedAgents: readonly string[]): Promise<AgentInstallOutcome[]>;
|
|
28
32
|
/** Formats a complete stdio entry for agents that add-mcp cannot configure. */
|
|
29
33
|
export declare function manualAgentConfiguration(plan: AgentSetupPlan): string;
|
|
30
34
|
export declare function projectAgentChoices(detected: readonly AgentType[]): Array<{
|
package/dist/agent-setup.js
CHANGED
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { copyFileSync, existsSync, readFileSync, realpathSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
2
4
|
import { join } from "node:path";
|
|
3
|
-
import { agents, detectGlobalAgents, detectProjectAgents, getAgentTypes, upsertServer, } from "add-mcp";
|
|
5
|
+
import { agents, detectGlobalAgents, detectProjectAgents, getAgentTypes, upsertServer, listInstalledServers, removeServer, } from "add-mcp";
|
|
4
6
|
import { installCommand } from "./installer.js";
|
|
5
7
|
export const nudgeServerName = "nudge_ui";
|
|
6
|
-
/**
|
|
7
|
-
export function planAgentSetup(projectRoot, packageManager, nudgeUiVersion) {
|
|
8
|
+
/** Plans the project bridge dependency and an independent, versioned adapter installation. */
|
|
9
|
+
export function planAgentSetup(projectRoot, packageManager, nudgeUiVersion, adapterDirectory = join(homedir(), ".nudge-ui", "adapters"), mcpPackageSpecifier) {
|
|
8
10
|
const canonicalRoot = realpathSync.native(projectRoot);
|
|
9
|
-
const packageSpecifier = `@nudge-ui/mcp@${nudgeUiVersion ?? installedNudgeUiVersion(canonicalRoot) ?? initializerVersion()}`;
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
command: "yarn",
|
|
15
|
-
args: ["--cwd", canonicalRoot, "exec", "nudge-mcp", "--workspace-root", canonicalRoot],
|
|
16
|
-
}
|
|
17
|
-
: {
|
|
18
|
-
command: "node",
|
|
19
|
-
args: [serverEntry, "--workspace-root", canonicalRoot],
|
|
20
|
-
};
|
|
11
|
+
const packageSpecifier = mcpPackageSpecifier ?? `@nudge-ui/mcp@${nudgeUiVersion ?? installedNudgeUiVersion(canonicalRoot) ?? initializerVersion()}`;
|
|
12
|
+
const adapterPackageSpecifier = mcpPackageSpecifier ?? `@nudge-ui/mcp@${initializerVersion()}`;
|
|
13
|
+
const adapterRoot = join(adapterDirectory, initializerVersion());
|
|
14
|
+
const serverEntry = join(adapterRoot, "node_modules", "@nudge-ui", "mcp", "dist", "cli.mjs");
|
|
15
|
+
const serverConfig = { command: process.execPath, args: [serverEntry] };
|
|
21
16
|
return {
|
|
22
17
|
projectRoot: canonicalRoot,
|
|
23
18
|
packageSpecifier,
|
|
24
19
|
installCommand: installCommand(packageManager, packageSpecifier),
|
|
25
20
|
serverConfig,
|
|
26
|
-
|
|
21
|
+
adapterRoot,
|
|
22
|
+
adapterInstallCommand: {
|
|
23
|
+
executable: "npm",
|
|
24
|
+
args: ["install", "--prefix", adapterRoot, "--no-save", "--package-lock=false", adapterPackageSpecifier],
|
|
25
|
+
},
|
|
26
|
+
serverEntry,
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
29
|
/** Checks that a node_modules based install produced the configured executable. */
|
|
30
30
|
export function isAgentServerAvailable(plan) {
|
|
31
|
-
return
|
|
31
|
+
return existsSync(plan.serverEntry);
|
|
32
32
|
}
|
|
33
|
-
/** Returns agents that
|
|
33
|
+
/** Returns agents that support a reusable stdio MCP configuration. */
|
|
34
34
|
export function projectAgentTypes() {
|
|
35
|
-
return getAgentTypes().filter((agent) => agents[agent].
|
|
35
|
+
return getAgentTypes().filter((agent) => agents[agent].supportedTransports.includes("stdio"));
|
|
36
36
|
}
|
|
37
|
-
/** Detects installed or already configured agents
|
|
37
|
+
/** Detects installed or already configured agents. */
|
|
38
38
|
export async function detectProjectAgentCandidates(projectRoot) {
|
|
39
39
|
const supported = new Set(projectAgentTypes());
|
|
40
40
|
const detected = [
|
|
@@ -43,25 +43,45 @@ export async function detectProjectAgentCandidates(projectRoot) {
|
|
|
43
43
|
].filter((agent) => supported.has(agent));
|
|
44
44
|
return [...new Set(detected)];
|
|
45
45
|
}
|
|
46
|
-
/**
|
|
47
|
-
export function configureProjectAgents(plan, selectedAgents) {
|
|
46
|
+
/** Registers the reusable adapter and removes the current project's overriding entry. */
|
|
47
|
+
export async function configureProjectAgents(plan, selectedAgents) {
|
|
48
48
|
const supported = new Set(projectAgentTypes());
|
|
49
|
-
|
|
49
|
+
const outcomes = [];
|
|
50
|
+
for (const agent of new Set(selectedAgents)) {
|
|
50
51
|
if (!supported.has(agent)) {
|
|
51
|
-
|
|
52
|
+
outcomes.push({ agent, displayName: agent, unsupported: true });
|
|
53
|
+
continue;
|
|
52
54
|
}
|
|
53
55
|
const agentType = agent;
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
const global = await listInstalledServers({ agents: [agentType], global: true, cwd: plan.projectRoot });
|
|
57
|
+
const local = agents[agentType].localConfigPath
|
|
58
|
+
? await listInstalledServers({ agents: [agentType], global: false, cwd: plan.projectRoot })
|
|
59
|
+
: [];
|
|
60
|
+
const configurations = [...global, ...local];
|
|
61
|
+
const invalid = configurations.find((configuration) => configuration.error);
|
|
62
|
+
if (invalid) {
|
|
63
|
+
outcomes.push({ agent, displayName: agents[agentType].displayName, unsupported: false,
|
|
64
|
+
result: { success: false, path: invalid.configPath, error: invalid.error } });
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const backups = [];
|
|
68
|
+
for (const configuration of configurations) {
|
|
69
|
+
if (!configuration.servers.some((server) => server.serverName === nudgeServerName))
|
|
70
|
+
continue;
|
|
71
|
+
const backup = `${configuration.configPath}.nudge-backup-${randomUUID()}`;
|
|
72
|
+
copyFileSync(configuration.configPath, backup);
|
|
73
|
+
backups.push(backup);
|
|
74
|
+
}
|
|
75
|
+
const result = upsertServer(agentType, nudgeServerName, plan.serverConfig, { local: false, cwd: plan.projectRoot });
|
|
76
|
+
const removal = result.success && agents[agentType].localConfigPath
|
|
77
|
+
? removeServer(agentType, nudgeServerName, { local: true, cwd: plan.projectRoot })
|
|
78
|
+
: undefined;
|
|
79
|
+
outcomes.push({
|
|
80
|
+
agent, displayName: agents[agentType].displayName, result, unsupported: false, backups,
|
|
81
|
+
...(removal && !removal.success ? { migrationError: removal.error ?? "Could not remove the project override." } : {}),
|
|
57
82
|
});
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
displayName: agents[agentType].displayName,
|
|
61
|
-
result,
|
|
62
|
-
unsupported: false,
|
|
63
|
-
};
|
|
64
|
-
});
|
|
83
|
+
}
|
|
84
|
+
return outcomes;
|
|
65
85
|
}
|
|
66
86
|
/** Formats a complete stdio entry for agents that add-mcp cannot configure. */
|
|
67
87
|
export function manualAgentConfiguration(plan) {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
3
|
+
/** Verifies the configured executable, initialization, and tools without claiming a project. */
|
|
4
|
+
export async function verifyAgentServer(config) {
|
|
5
|
+
if (!config.command)
|
|
6
|
+
throw new Error("The MCP adapter has no executable.");
|
|
7
|
+
const client = new Client({ name: "nudge-setup", version: "1.0.0" });
|
|
8
|
+
const transport = new StdioClientTransport({ command: config.command, args: config.args, stderr: "inherit" });
|
|
9
|
+
try {
|
|
10
|
+
await client.connect(transport, { timeout: 15_000 });
|
|
11
|
+
const { tools } = await client.listTools({}, { timeout: 15_000 });
|
|
12
|
+
const listen = tools.find((tool) => tool.name === "nudge_listen");
|
|
13
|
+
if (!listen?.inputSchema.required?.includes("workspaceRoot") || !tools.some((tool) => tool.name === "nudge_list_sessions")) {
|
|
14
|
+
throw new Error("The installed adapter does not support connection-time project selection. Upgrade @nudge-ui/mcp.");
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
finally {
|
|
18
|
+
await transport.close();
|
|
19
|
+
await client.close();
|
|
20
|
+
}
|
|
21
|
+
}
|
package/dist/arguments.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export interface CliOptions {
|
|
|
4
4
|
readonly packageManager?: PackageManager;
|
|
5
5
|
readonly agentOnly: boolean;
|
|
6
6
|
readonly agents: readonly string[];
|
|
7
|
+
readonly mcpPackageSpecifier?: string;
|
|
7
8
|
readonly mcp?: boolean;
|
|
8
9
|
readonly yes: boolean;
|
|
9
10
|
readonly dryRun: boolean;
|
|
@@ -11,4 +12,4 @@ export interface CliOptions {
|
|
|
11
12
|
}
|
|
12
13
|
/** Parses the initializer command line. */
|
|
13
14
|
export declare function parseArguments(args: readonly string[]): CliOptions;
|
|
14
|
-
export declare const helpText = "Set up Nudge UI in the current project.\n\nUsage: npm create nudge-ui@latest -- [options]\n\nOptions:\n --framework <nextjs|astro|vite-react|standalone>\n --package-manager <pnpm|npm|yarn|bun>\n --mcp Configure the
|
|
15
|
+
export declare const helpText = "Set up Nudge UI in the current project.\n\nUsage: npm create nudge-ui@latest -- [options]\n\nOptions:\n --framework <nextjs|astro|vite-react|standalone>\n --package-manager <pnpm|npm|yarn|bun>\n --mcp Configure the reusable Nudge MCP adapter\n --no-mcp Skip coding-agent setup\n --agent <id> Configure a supported agent (repeatable)\n --mcp-package <path|package> Use this MCP package for the project and adapter\n --agent-only Install or repair only the agent integration\n -y, --yes Accept defaults without prompting\n --dry-run\n -h, --help";
|
package/dist/arguments.js
CHANGED
|
@@ -5,6 +5,7 @@ export function parseArguments(args) {
|
|
|
5
5
|
let packageManager;
|
|
6
6
|
let agentOnly = false;
|
|
7
7
|
const agents = [];
|
|
8
|
+
let mcpPackageSpecifier;
|
|
8
9
|
let mcp;
|
|
9
10
|
let yes = false;
|
|
10
11
|
let dryRun = false;
|
|
@@ -32,6 +33,10 @@ export function parseArguments(args) {
|
|
|
32
33
|
agents.push(requiredValue(args, ++index, argument));
|
|
33
34
|
else if (argument.startsWith("--agent="))
|
|
34
35
|
agents.push(requiredValue([argument.slice("--agent=".length)], 0, "--agent"));
|
|
36
|
+
else if (argument === "--mcp-package")
|
|
37
|
+
mcpPackageSpecifier = requiredValue(args, ++index, argument);
|
|
38
|
+
else if (argument.startsWith("--mcp-package="))
|
|
39
|
+
mcpPackageSpecifier = requiredValue([argument.slice("--mcp-package=".length)], 0, "--mcp-package");
|
|
35
40
|
else if (argument === "--help" || argument === "-h")
|
|
36
41
|
help = true;
|
|
37
42
|
else if (argument === "--framework")
|
|
@@ -51,7 +56,7 @@ export function parseArguments(args) {
|
|
|
51
56
|
throw new Error("--agent cannot be combined with --no-mcp.");
|
|
52
57
|
if (agentOnly && mcp === false)
|
|
53
58
|
throw new Error("--agent-only cannot be combined with --no-mcp.");
|
|
54
|
-
return { framework, packageManager, agentOnly, agents, mcp, yes, dryRun, help };
|
|
59
|
+
return { framework, packageManager, agentOnly, agents, mcpPackageSpecifier, mcp, yes, dryRun, help };
|
|
55
60
|
}
|
|
56
61
|
function setMcpPreference(current, next) {
|
|
57
62
|
if (current !== undefined && current !== next)
|
|
@@ -71,9 +76,10 @@ Usage: npm create nudge-ui@latest -- [options]
|
|
|
71
76
|
Options:
|
|
72
77
|
--framework <nextjs|astro|vite-react|standalone>
|
|
73
78
|
--package-manager <pnpm|npm|yarn|bun>
|
|
74
|
-
--mcp Configure the
|
|
79
|
+
--mcp Configure the reusable Nudge MCP adapter
|
|
75
80
|
--no-mcp Skip coding-agent setup
|
|
76
81
|
--agent <id> Configure a supported agent (repeatable)
|
|
82
|
+
--mcp-package <path|package> Use this MCP package for the project and adapter
|
|
77
83
|
--agent-only Install or repair only the agent integration
|
|
78
84
|
-y, --yes Accept defaults without prompting
|
|
79
85
|
--dry-run
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type PackageManager } from "./types.js";
|
|
2
2
|
export interface RunAgentSetupOptions {
|
|
3
3
|
readonly agents?: readonly string[];
|
|
4
|
+
/** Optional package specifier or tarball used for both bridge and adapter testing. */
|
|
5
|
+
readonly mcpPackageSpecifier?: string;
|
|
4
6
|
readonly dryRun?: boolean;
|
|
5
7
|
readonly nudgeUiVersion?: string;
|
|
6
8
|
readonly packageManager?: PackageManager;
|
|
@@ -8,5 +10,5 @@ export interface RunAgentSetupOptions {
|
|
|
8
10
|
}
|
|
9
11
|
/** Runs the Nudge UI project initializer. */
|
|
10
12
|
export declare function runCli(args?: string[], projectRoot?: string): Promise<void>;
|
|
11
|
-
/** Installs and configures the
|
|
13
|
+
/** Installs and configures the reusable MCP adapter and project bridge dependency. Safe to rerun for repairs. */
|
|
12
14
|
export declare function runAgentSetup(projectRoot?: string, options?: RunAgentSetupOptions): Promise<void>;
|
package/dist/cli.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { rmSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { verifyAgentServer } from "./agent-verification.js";
|
|
2
3
|
import { createInterface } from "node:readline/promises";
|
|
3
4
|
import { stdin, stdout } from "node:process";
|
|
4
5
|
import { basename, relative } from "node:path";
|
|
@@ -20,6 +21,7 @@ export async function runCli(args = process.argv.slice(2), projectRoot = process
|
|
|
20
21
|
if (options.agentOnly) {
|
|
21
22
|
await runAgentSetup(projectRoot, {
|
|
22
23
|
agents: options.agents,
|
|
24
|
+
mcpPackageSpecifier: options.mcpPackageSpecifier,
|
|
23
25
|
dryRun: options.dryRun,
|
|
24
26
|
packageManager,
|
|
25
27
|
yes: options.yes,
|
|
@@ -44,6 +46,7 @@ export async function runCli(args = process.argv.slice(2), projectRoot = process
|
|
|
44
46
|
if (await shouldConfigureAgent(options.mcp, options.agents.length > 0, options.yes)) {
|
|
45
47
|
await runAgentSetup(projectRoot, {
|
|
46
48
|
agents: options.agents,
|
|
49
|
+
mcpPackageSpecifier: options.mcpPackageSpecifier,
|
|
47
50
|
dryRun: true,
|
|
48
51
|
nudgeUiVersion: initializerVersion(),
|
|
49
52
|
packageManager,
|
|
@@ -73,17 +76,18 @@ export async function runCli(args = process.argv.slice(2), projectRoot = process
|
|
|
73
76
|
if (await shouldConfigureAgent(options.mcp, options.agents.length > 0, options.yes)) {
|
|
74
77
|
await runAgentSetup(projectRoot, {
|
|
75
78
|
agents: options.agents,
|
|
79
|
+
mcpPackageSpecifier: options.mcpPackageSpecifier,
|
|
76
80
|
nudgeUiVersion: initializerVersion(),
|
|
77
81
|
packageManager,
|
|
78
82
|
yes: options.yes,
|
|
79
83
|
});
|
|
80
84
|
}
|
|
81
85
|
}
|
|
82
|
-
/** Installs and configures the
|
|
86
|
+
/** Installs and configures the reusable MCP adapter and project bridge dependency. Safe to rerun for repairs. */
|
|
83
87
|
export async function runAgentSetup(projectRoot = process.cwd(), options = {}) {
|
|
84
88
|
const manifest = readProjectManifest(projectRoot);
|
|
85
89
|
const packageManager = options.packageManager ?? detectPackageManager(projectRoot, manifest);
|
|
86
|
-
const plan = planAgentSetup(projectRoot, packageManager, options.nudgeUiVersion);
|
|
90
|
+
const plan = planAgentSetup(projectRoot, packageManager, options.nudgeUiVersion, undefined, options.mcpPackageSpecifier);
|
|
87
91
|
const detected = await detectProjectAgentCandidates(plan.projectRoot);
|
|
88
92
|
const selected = options.agents && options.agents.length > 0
|
|
89
93
|
? options.agents
|
|
@@ -92,8 +96,9 @@ export async function runAgentSetup(projectRoot = process.cwd(), options = {}) {
|
|
|
92
96
|
: await selectAgents(detected);
|
|
93
97
|
if (options.dryRun) {
|
|
94
98
|
stdout.write(`Would run: ${formatCommand(plan.installCommand)}\n`);
|
|
99
|
+
stdout.write(`Would run: ${formatCommand(plan.adapterInstallCommand)}\n`);
|
|
95
100
|
if (selected.length > 0) {
|
|
96
|
-
stdout.write(`Would configure
|
|
101
|
+
stdout.write(`Would configure global MCP and migrate this project override for: ${selected.join(", ")}\n`);
|
|
97
102
|
}
|
|
98
103
|
else {
|
|
99
104
|
stdout.write("No coding agent was detected. Use --agent <id> or add the configuration below manually.\n");
|
|
@@ -102,11 +107,33 @@ export async function runAgentSetup(projectRoot = process.cwd(), options = {}) {
|
|
|
102
107
|
return;
|
|
103
108
|
}
|
|
104
109
|
installPackage(plan.installCommand, plan.projectRoot);
|
|
110
|
+
try {
|
|
111
|
+
mkdirSync(plan.adapterRoot, { recursive: true });
|
|
112
|
+
installPackage(plan.adapterInstallCommand, plan.adapterRoot);
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
116
|
+
stdout.write(`Could not install the reusable MCP adapter: ${message}\n`);
|
|
117
|
+
stdout.write(`Retry with: ${formatCommand(plan.adapterInstallCommand)}\n`);
|
|
118
|
+
stdout.write("The coding-agent configuration was not changed. After the adapter install succeeds, rerun with --agent-only.\n");
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
105
121
|
if (!isAgentServerAvailable(plan)) {
|
|
106
|
-
stdout.write(`Installed ${plan.packageSpecifier}, but its
|
|
122
|
+
stdout.write(`Installed ${plan.packageSpecifier}, but its reusable MCP executable was not found at ${plan.serverEntry}.\n`);
|
|
123
|
+
stdout.write(`Retry with: ${formatCommand(plan.adapterInstallCommand)}\n`);
|
|
107
124
|
stdout.write("The coding-agent configuration was not changed. Check the package-manager install output, then rerun with --agent-only.\n");
|
|
108
125
|
return;
|
|
109
126
|
}
|
|
127
|
+
try {
|
|
128
|
+
await verifyAgentServer(plan.serverConfig);
|
|
129
|
+
stdout.write("Verified MCP initialization and tool discovery with a fresh client.\n");
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
stdout.write(`MCP verification failed: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
133
|
+
stdout.write(`Retry with: ${formatCommand(plan.adapterInstallCommand)}\n`);
|
|
134
|
+
stdout.write("The coding-agent configuration was not changed. After repairing the adapter install, rerun with --agent-only.\n");
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
110
137
|
if (selected.length === 0) {
|
|
111
138
|
stdout.write(`Installed ${plan.packageSpecifier}, but no coding agent was detected.\n`);
|
|
112
139
|
writeManualInstructions(plan);
|
|
@@ -114,7 +141,7 @@ export async function runAgentSetup(projectRoot = process.cwd(), options = {}) {
|
|
|
114
141
|
}
|
|
115
142
|
let outcomes;
|
|
116
143
|
try {
|
|
117
|
-
outcomes = configureProjectAgents(plan, selected);
|
|
144
|
+
outcomes = await configureProjectAgents(plan, selected);
|
|
118
145
|
}
|
|
119
146
|
catch (error) {
|
|
120
147
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -125,7 +152,13 @@ export async function runAgentSetup(projectRoot = process.cwd(), options = {}) {
|
|
|
125
152
|
let configured = 0;
|
|
126
153
|
for (const outcome of outcomes) {
|
|
127
154
|
if (outcome.unsupported) {
|
|
128
|
-
stdout.write(`${outcome.displayName} is not supported for automatic
|
|
155
|
+
stdout.write(`${outcome.displayName} is not supported for automatic global setup.\n`);
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
for (const backup of outcome.backups ?? [])
|
|
159
|
+
stdout.write(`Saved previous MCP configuration: ${backup}\n`);
|
|
160
|
+
if (outcome.migrationError) {
|
|
161
|
+
stdout.write(`Global adapter configured, but project override migration failed: ${outcome.migrationError}\n`);
|
|
129
162
|
continue;
|
|
130
163
|
}
|
|
131
164
|
if (outcome.result?.success) {
|
|
@@ -138,7 +171,7 @@ export async function runAgentSetup(projectRoot = process.cwd(), options = {}) {
|
|
|
138
171
|
if (configured !== outcomes.length)
|
|
139
172
|
writeManualInstructions(plan);
|
|
140
173
|
if (configured > 0) {
|
|
141
|
-
stdout.write("
|
|
174
|
+
stdout.write("Adapter configuration is ready. Fully restart the agent host to load it, then ask it to listen to Nudge in the current workspace. Existing overrides in other projects require one setup rerun there.\n");
|
|
142
175
|
}
|
|
143
176
|
}
|
|
144
177
|
async function shouldConfigureAgent(preference, hasExplicitAgents, yes) {
|
|
@@ -189,7 +222,7 @@ async function selectAgents(detected) {
|
|
|
189
222
|
}
|
|
190
223
|
}
|
|
191
224
|
function writeManualInstructions(plan) {
|
|
192
|
-
stdout.write("Add this
|
|
225
|
+
stdout.write("Add this global stdio server to your agent's MCP settings:\n");
|
|
193
226
|
stdout.write(`${manualAgentConfiguration(plan)}\n`);
|
|
194
227
|
}
|
|
195
228
|
async function selectFramework(detected) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-nudge-ui",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Framework-detecting installer for Nudge UI.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"add-mcp": "^2.4.0",
|
|
33
|
-
"typescript": "^5.9.3"
|
|
33
|
+
"typescript": "^5.9.3",
|
|
34
|
+
"@modelcontextprotocol/sdk": "^1.30.0"
|
|
34
35
|
},
|
|
35
36
|
"devDependencies": {
|
|
36
37
|
"vitest": "^2.1.9"
|