agentinit 1.6.0 → 1.8.0
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/CHANGELOG.md +40 -0
- package/README.md +220 -114
- package/dist/agents/Agent.d.ts +44 -0
- package/dist/agents/Agent.d.ts.map +1 -1
- package/dist/agents/Agent.js +111 -22
- package/dist/agents/Agent.js.map +1 -1
- package/dist/agents/AiderAgent.d.ts +9 -0
- package/dist/agents/AiderAgent.d.ts.map +1 -0
- package/dist/agents/AiderAgent.js +135 -0
- package/dist/agents/AiderAgent.js.map +1 -0
- package/dist/agents/ClaudeAgent.d.ts +4 -0
- package/dist/agents/ClaudeAgent.d.ts.map +1 -1
- package/dist/agents/ClaudeAgent.js +33 -18
- package/dist/agents/ClaudeAgent.js.map +1 -1
- package/dist/agents/ClaudeDesktopAgent.d.ts +5 -0
- package/dist/agents/ClaudeDesktopAgent.d.ts.map +1 -1
- package/dist/agents/ClaudeDesktopAgent.js +31 -1
- package/dist/agents/ClaudeDesktopAgent.js.map +1 -1
- package/dist/agents/ClineAgent.d.ts +8 -0
- package/dist/agents/ClineAgent.d.ts.map +1 -0
- package/dist/agents/ClineAgent.js +42 -0
- package/dist/agents/ClineAgent.js.map +1 -0
- package/dist/agents/CodexCliAgent.d.ts +4 -0
- package/dist/agents/CodexCliAgent.d.ts.map +1 -1
- package/dist/agents/CodexCliAgent.js +38 -8
- package/dist/agents/CodexCliAgent.js.map +1 -1
- package/dist/agents/CopilotAgent.d.ts +9 -0
- package/dist/agents/CopilotAgent.d.ts.map +1 -0
- package/dist/agents/CopilotAgent.js +131 -0
- package/dist/agents/CopilotAgent.js.map +1 -0
- package/dist/agents/CursorAgent.d.ts +4 -4
- package/dist/agents/CursorAgent.d.ts.map +1 -1
- package/dist/agents/CursorAgent.js +32 -43
- package/dist/agents/CursorAgent.js.map +1 -1
- package/dist/agents/DroidAgent.d.ts +5 -0
- package/dist/agents/DroidAgent.d.ts.map +1 -1
- package/dist/agents/DroidAgent.js +37 -18
- package/dist/agents/DroidAgent.js.map +1 -1
- package/dist/agents/GeminiCliAgent.d.ts +4 -0
- package/dist/agents/GeminiCliAgent.d.ts.map +1 -1
- package/dist/agents/GeminiCliAgent.js +37 -8
- package/dist/agents/GeminiCliAgent.js.map +1 -1
- package/dist/agents/MarkdownRulesAgent.d.ts +13 -0
- package/dist/agents/MarkdownRulesAgent.d.ts.map +1 -0
- package/dist/agents/MarkdownRulesAgent.js +53 -0
- package/dist/agents/MarkdownRulesAgent.js.map +1 -0
- package/dist/agents/RooCodeAgent.d.ts +9 -0
- package/dist/agents/RooCodeAgent.d.ts.map +1 -0
- package/dist/agents/RooCodeAgent.js +131 -0
- package/dist/agents/RooCodeAgent.js.map +1 -0
- package/dist/agents/WindsurfAgent.d.ts +9 -0
- package/dist/agents/WindsurfAgent.d.ts.map +1 -0
- package/dist/agents/WindsurfAgent.js +127 -0
- package/dist/agents/WindsurfAgent.js.map +1 -0
- package/dist/agents/ZedAgent.d.ts +9 -0
- package/dist/agents/ZedAgent.d.ts.map +1 -0
- package/dist/agents/ZedAgent.js +127 -0
- package/dist/agents/ZedAgent.js.map +1 -0
- package/dist/cli.js +29992 -11107
- package/dist/cli.js.map +1 -1
- package/dist/commands/apply.d.ts +10 -0
- package/dist/commands/apply.d.ts.map +1 -1
- package/dist/commands/apply.js +136 -5
- package/dist/commands/apply.js.map +1 -1
- package/dist/commands/detect.d.ts.map +1 -1
- package/dist/commands/detect.js +25 -0
- package/dist/commands/detect.js.map +1 -1
- package/dist/commands/init.js +1 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/mcp.d.ts +2 -7
- package/dist/commands/mcp.d.ts.map +1 -1
- package/dist/commands/mcp.js +541 -110
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/plugins.d.ts +3 -0
- package/dist/commands/plugins.d.ts.map +1 -0
- package/dist/commands/plugins.js +309 -0
- package/dist/commands/plugins.js.map +1 -0
- package/dist/commands/revert.d.ts +7 -0
- package/dist/commands/revert.d.ts.map +1 -0
- package/dist/commands/revert.js +48 -0
- package/dist/commands/revert.js.map +1 -0
- package/dist/commands/rules.d.ts +3 -0
- package/dist/commands/rules.d.ts.map +1 -0
- package/dist/commands/rules.js +354 -0
- package/dist/commands/rules.js.map +1 -0
- package/dist/commands/skills.d.ts +3 -0
- package/dist/commands/skills.d.ts.map +1 -0
- package/dist/commands/skills.js +179 -0
- package/dist/commands/skills.js.map +1 -0
- package/dist/commands/sync.d.ts +1 -0
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +18 -1
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/verifyMcp.d.ts.map +1 -1
- package/dist/commands/verifyMcp.js +27 -5
- package/dist/commands/verifyMcp.js.map +1 -1
- package/dist/constants/index.d.ts +1 -1
- package/dist/constants/index.d.ts.map +1 -1
- package/dist/constants/index.js +1 -1
- package/dist/constants/index.js.map +1 -1
- package/dist/constants/mcp.d.ts +1 -0
- package/dist/constants/mcp.d.ts.map +1 -1
- package/dist/constants/mcp.js +2 -0
- package/dist/constants/mcp.js.map +1 -1
- package/dist/core/agentDetector.d.ts.map +1 -1
- package/dist/core/agentDetector.js +8 -2
- package/dist/core/agentDetector.js.map +1 -1
- package/dist/core/agentManager.d.ts.map +1 -1
- package/dist/core/agentManager.js +12 -0
- package/dist/core/agentManager.js.map +1 -1
- package/dist/core/gitignoreManager.d.ts +8 -0
- package/dist/core/gitignoreManager.d.ts.map +1 -0
- package/dist/core/gitignoreManager.js +114 -0
- package/dist/core/gitignoreManager.js.map +1 -0
- package/dist/core/managedState.d.ts +42 -0
- package/dist/core/managedState.d.ts.map +1 -0
- package/dist/core/managedState.js +194 -0
- package/dist/core/managedState.js.map +1 -0
- package/dist/core/mcpClient.d.ts +124 -6
- package/dist/core/mcpClient.d.ts.map +1 -1
- package/dist/core/mcpClient.js +385 -39
- package/dist/core/mcpClient.js.map +1 -1
- package/dist/core/pluginManager.d.ts +134 -0
- package/dist/core/pluginManager.d.ts.map +1 -0
- package/dist/core/pluginManager.js +845 -0
- package/dist/core/pluginManager.js.map +1 -0
- package/dist/core/projectSkills.d.ts +19 -0
- package/dist/core/projectSkills.d.ts.map +1 -0
- package/dist/core/projectSkills.js +105 -0
- package/dist/core/projectSkills.js.map +1 -0
- package/dist/core/propagator.d.ts +8 -1
- package/dist/core/propagator.d.ts.map +1 -1
- package/dist/core/propagator.js +179 -36
- package/dist/core/propagator.js.map +1 -1
- package/dist/core/rulesApplicator.d.ts +0 -4
- package/dist/core/rulesApplicator.d.ts.map +1 -1
- package/dist/core/rulesApplicator.js +8 -39
- package/dist/core/rulesApplicator.js.map +1 -1
- package/dist/core/rulesTemplateLoader.js +2 -2
- package/dist/core/rulesTemplateLoader.js.map +1 -1
- package/dist/core/skillsManager.d.ts +61 -0
- package/dist/core/skillsManager.d.ts.map +1 -0
- package/dist/core/skillsManager.js +407 -0
- package/dist/core/skillsManager.js.map +1 -0
- package/dist/lib/utils/index.d.ts +3 -1
- package/dist/lib/utils/index.d.ts.map +1 -1
- package/dist/lib/utils/index.js +4 -1
- package/dist/lib/utils/index.js.map +1 -1
- package/dist/types/index.d.ts +24 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/jsonSchema.d.ts +31 -0
- package/dist/types/jsonSchema.d.ts.map +1 -0
- package/dist/types/jsonSchema.js +6 -0
- package/dist/types/jsonSchema.js.map +1 -0
- package/dist/types/plugins.d.ts +161 -0
- package/dist/types/plugins.d.ts.map +1 -0
- package/dist/types/plugins.js +2 -0
- package/dist/types/plugins.js.map +1 -0
- package/dist/types/skills.d.ts +50 -0
- package/dist/types/skills.d.ts.map +1 -0
- package/dist/types/skills.js +2 -0
- package/dist/types/skills.js.map +1 -0
- package/dist/utils/packageVersion.d.ts +105 -0
- package/dist/utils/packageVersion.d.ts.map +1 -0
- package/dist/utils/packageVersion.js +219 -0
- package/dist/utils/packageVersion.js.map +1 -0
- package/package.json +7 -2
- package/dist/agentinit-1.6.0.tgz +0 -0
- package/dist/registry/mcpRegistry.d.ts +0 -12
- package/dist/registry/mcpRegistry.d.ts.map +0 -1
- package/dist/registry/mcpRegistry.js +0 -114
- package/dist/registry/mcpRegistry.js.map +0 -1
package/dist/commands/mcp.js
CHANGED
|
@@ -1,127 +1,558 @@
|
|
|
1
1
|
import ora from 'ora';
|
|
2
|
-
import
|
|
3
|
-
import { exec } from 'child_process';
|
|
4
|
-
import { promisify } from 'util';
|
|
2
|
+
import { green, cyan, yellow, red } from 'kleur/colors';
|
|
5
3
|
import { logger } from '../utils/logger.js';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
4
|
+
import { MCPParser, MCPParseError } from '../core/mcpParser.js';
|
|
5
|
+
import { MCPVerifier } from '../core/mcpClient.js';
|
|
6
|
+
import { MCPFilter } from '../core/mcpFilter.js';
|
|
7
|
+
import { AgentManager } from '../core/agentManager.js';
|
|
8
|
+
import { DEFAULT_CONNECTION_TIMEOUT_MS } from '../constants/index.js';
|
|
9
|
+
/**
|
|
10
|
+
* Options that `mcp add` recognizes and must be stripped before
|
|
11
|
+
* passing the remaining argv to MCPParser.
|
|
12
|
+
*
|
|
13
|
+
* Map key = the flag itself
|
|
14
|
+
* Map value = true if the flag takes a value argument, false if boolean
|
|
15
|
+
*/
|
|
16
|
+
const KNOWN_ADD_OPTIONS = {
|
|
17
|
+
'--agent': true,
|
|
18
|
+
'--global': false,
|
|
19
|
+
'--verify': false,
|
|
20
|
+
'--timeout': true,
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Strip known CLI options (and their values) from the raw arg list
|
|
24
|
+
* so that only `--mcp-*` flags and their modifiers remain.
|
|
25
|
+
*/
|
|
26
|
+
function filterMcpArgs(args) {
|
|
27
|
+
const filtered = [];
|
|
28
|
+
let i = 0;
|
|
29
|
+
while (i < args.length) {
|
|
30
|
+
const arg = args[i];
|
|
31
|
+
const meta = KNOWN_ADD_OPTIONS[arg];
|
|
32
|
+
if (meta !== undefined) {
|
|
33
|
+
// Skip the flag itself
|
|
34
|
+
i++;
|
|
35
|
+
// If it takes a value, also skip the next token
|
|
36
|
+
if (meta && i < args.length) {
|
|
37
|
+
i++;
|
|
38
|
+
}
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
filtered.push(arg);
|
|
42
|
+
i++;
|
|
33
43
|
}
|
|
34
|
-
|
|
35
|
-
results.forEach(mcp => displayMCP(mcp));
|
|
44
|
+
return filtered;
|
|
36
45
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Resolve the list of agents to operate on.
|
|
48
|
+
*
|
|
49
|
+
* - If `agentIds` is provided, look up each one explicitly.
|
|
50
|
+
* - If `isGlobal` is set without agents, error out (global requires explicit agent).
|
|
51
|
+
* - Otherwise auto-detect agents in the current project.
|
|
52
|
+
*/
|
|
53
|
+
async function resolveAgents(agentManager, agentIds, isGlobal, cwd) {
|
|
54
|
+
if (agentIds && agentIds.length > 0) {
|
|
55
|
+
const results = [];
|
|
56
|
+
for (const id of agentIds) {
|
|
57
|
+
const agent = agentManager.getAgentById(id);
|
|
58
|
+
if (!agent) {
|
|
59
|
+
logger.error(`Unknown agent: ${id}`);
|
|
60
|
+
logger.info(`Supported agents: ${agentManager.getSupportedAgentIds().join(', ')}`);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
if (isGlobal && !agent.supportsGlobalConfig()) {
|
|
64
|
+
logger.error(`Agent ${agent.name} does not support global configuration`);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
if (!isGlobal) {
|
|
68
|
+
const detection = await agent.detectPresence(cwd);
|
|
69
|
+
if (!detection) {
|
|
70
|
+
logger.warning(`Agent ${id} not detected in project, skipping`);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
results.push({ agent, isGlobal });
|
|
75
|
+
}
|
|
76
|
+
return results;
|
|
42
77
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
spinner.succeed(`${mcp.name} installed successfully`);
|
|
47
|
-
logger.info('Agent Instructions:');
|
|
48
|
-
logger.info(mcp.agentInstructions);
|
|
78
|
+
if (isGlobal) {
|
|
79
|
+
logger.error('--global requires --agent to specify target agent(s)');
|
|
80
|
+
process.exit(1);
|
|
49
81
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
82
|
+
// Auto-detect
|
|
83
|
+
const detected = await agentManager.detectAgents(cwd);
|
|
84
|
+
if (detected.length === 0) {
|
|
85
|
+
logger.warning('No AI coding agents detected in this project');
|
|
86
|
+
logger.info('Supported agents:');
|
|
87
|
+
agentManager.getAllAgents().forEach(a => {
|
|
88
|
+
logger.info(` - ${a.name} (${a.id})`);
|
|
89
|
+
});
|
|
90
|
+
logger.info('');
|
|
91
|
+
logger.info('To target a specific agent, use: --agent <agent-id>');
|
|
92
|
+
return [];
|
|
53
93
|
}
|
|
94
|
+
return detected.map(d => ({ agent: d.agent, isGlobal: false }));
|
|
54
95
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
// Subcommand: mcp add
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
function registerAddCommand(mcp) {
|
|
100
|
+
mcp
|
|
101
|
+
.command('add')
|
|
102
|
+
.description('Add MCP server(s) to agent configurations')
|
|
103
|
+
.allowUnknownOption(true)
|
|
104
|
+
.option('--agent <agents...>', 'Target specific agent(s)')
|
|
105
|
+
.option('-g, --global', 'Apply to global configuration')
|
|
106
|
+
.option('--verify', 'Verify MCP servers after adding')
|
|
107
|
+
.option('--timeout <ms>', 'Connection timeout for verification (ms)')
|
|
108
|
+
.action(async (options, command) => {
|
|
109
|
+
const cwd = process.cwd();
|
|
110
|
+
// Extract raw args that come after "mcp add"
|
|
111
|
+
const allArgs = command.parent.parent.rawArgs;
|
|
112
|
+
const addIdx = allArgs.indexOf('add');
|
|
113
|
+
if (addIdx < 0) {
|
|
114
|
+
logger.error('Internal error: could not locate "add" in raw arguments');
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
const rawArgs = allArgs.slice(addIdx + 1);
|
|
118
|
+
// Strip known options so only --mcp-* flags remain
|
|
119
|
+
const mcpArgs = filterMcpArgs(rawArgs);
|
|
120
|
+
if (mcpArgs.length === 0 || !mcpArgs.some(a => a.startsWith('--mcp-'))) {
|
|
121
|
+
logger.info('Usage: agentinit mcp add [options] --mcp-stdio|--mcp-http|--mcp-sse <name> <command|url> [modifiers]');
|
|
122
|
+
logger.info('');
|
|
123
|
+
logger.info('Options:');
|
|
124
|
+
logger.info(' --agent <agents...> Target specific agent(s)');
|
|
125
|
+
logger.info(' -g, --global Apply to global configuration');
|
|
126
|
+
logger.info(' --verify Verify MCP servers after adding');
|
|
127
|
+
logger.info(` --timeout <ms> Verification timeout (default: ${DEFAULT_CONNECTION_TIMEOUT_MS})`);
|
|
128
|
+
logger.info('');
|
|
129
|
+
logger.info('Examples:');
|
|
130
|
+
logger.info(' agentinit mcp add --mcp-stdio exa "npx -y @exa/mcp-server" --env "EXA_API_KEY=key"');
|
|
131
|
+
logger.info(' agentinit mcp add --agent claude --mcp-http github "https://api.github.com/mcp" --auth "Bearer token"');
|
|
132
|
+
logger.info(' agentinit mcp add --global --agent claude --mcp-stdio fs "npx -y @modelcontextprotocol/server-filesystem" --args "/home"');
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const spinner = ora('Parsing MCP configuration...').start();
|
|
136
|
+
try {
|
|
137
|
+
const parsed = MCPParser.parseArguments(mcpArgs);
|
|
138
|
+
if (parsed.servers.length === 0) {
|
|
139
|
+
spinner.warn('No MCP servers found in arguments');
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
spinner.text = 'Resolving target agents...';
|
|
143
|
+
const agentManager = new AgentManager();
|
|
144
|
+
const isGlobal = !!options.global;
|
|
145
|
+
const targets = await resolveAgents(agentManager, options.agent, isGlobal, cwd);
|
|
146
|
+
if (targets.length === 0) {
|
|
147
|
+
spinner.warn('No target agents resolved');
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
let totalApplied = 0;
|
|
151
|
+
for (const { agent, isGlobal: global } of targets) {
|
|
152
|
+
spinner.text = `Applying to ${agent.name}...`;
|
|
153
|
+
const filtered = MCPFilter.filterForAgent(agent, parsed.servers);
|
|
154
|
+
if (filtered.servers.length === 0) {
|
|
155
|
+
logger.warning(`${agent.name}: No compatible MCP servers`);
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
if (global) {
|
|
159
|
+
await agent.applyGlobalMCPConfig(filtered.servers);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
await agent.applyMCPConfig(cwd, filtered.servers);
|
|
163
|
+
}
|
|
164
|
+
totalApplied += filtered.servers.length;
|
|
165
|
+
const configPath = global
|
|
166
|
+
? agent.getGlobalMcpPath()
|
|
167
|
+
: agent.getNativeMcpPath(cwd);
|
|
168
|
+
logger.info(` ${green('+')} ${agent.name}: ${filtered.servers.length} server(s) added`);
|
|
169
|
+
if (configPath) {
|
|
170
|
+
logger.info(` Config: ${configPath}`);
|
|
171
|
+
}
|
|
172
|
+
if (filtered.transformations.length > 0) {
|
|
173
|
+
filtered.transformations.forEach(t => {
|
|
174
|
+
logger.info(` ${yellow('~')} ${t.original.name}: ${t.reason}`);
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (totalApplied === 0) {
|
|
179
|
+
spinner.warn('No servers were applied (all filtered out)');
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
spinner.succeed(`Added ${totalApplied} MCP server(s)`);
|
|
183
|
+
// List what was added
|
|
184
|
+
parsed.servers.forEach(server => {
|
|
185
|
+
const typeLabel = server.type.toUpperCase();
|
|
186
|
+
if (server.type === 'stdio' && server.command) {
|
|
187
|
+
logger.info(` ${cyan(server.name)} (${typeLabel}): ${server.command} ${server.args?.join(' ') || ''}`);
|
|
188
|
+
}
|
|
189
|
+
else if (server.url) {
|
|
190
|
+
logger.info(` ${cyan(server.name)} (${typeLabel}): ${server.url}`);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
// Verify if requested
|
|
195
|
+
if (options.verify && parsed.servers.length > 0) {
|
|
196
|
+
logger.info('');
|
|
197
|
+
const timeout = options.timeout ? parseInt(options.timeout, 10) : undefined;
|
|
198
|
+
await runVerification(parsed.servers, timeout);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
spinner.fail('Failed to add MCP servers');
|
|
203
|
+
if (error instanceof MCPParseError) {
|
|
204
|
+
logger.error(error.message);
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
logger.error(`${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
208
|
+
}
|
|
209
|
+
process.exit(1);
|
|
210
|
+
}
|
|
74
211
|
});
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
212
|
+
}
|
|
213
|
+
// ---------------------------------------------------------------------------
|
|
214
|
+
// Subcommand: mcp list (alias: ls)
|
|
215
|
+
// ---------------------------------------------------------------------------
|
|
216
|
+
function registerListCommand(mcp) {
|
|
217
|
+
mcp
|
|
218
|
+
.command('list')
|
|
219
|
+
.alias('ls')
|
|
220
|
+
.description('List configured MCP servers')
|
|
221
|
+
.option('--agent <agents...>', 'Target specific agent(s)')
|
|
222
|
+
.option('-g, --global', 'List global configuration')
|
|
223
|
+
.action(async (options) => {
|
|
224
|
+
const cwd = process.cwd();
|
|
225
|
+
const agentManager = new AgentManager();
|
|
226
|
+
const isGlobal = !!options.global;
|
|
227
|
+
const spinner = ora('Reading MCP configurations...').start();
|
|
228
|
+
try {
|
|
229
|
+
const targets = await resolveAgents(agentManager, options.agent, isGlobal, cwd);
|
|
230
|
+
if (targets.length === 0) {
|
|
231
|
+
spinner.warn('No target agents resolved');
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
spinner.stop();
|
|
235
|
+
let totalServers = 0;
|
|
236
|
+
for (const { agent, isGlobal: global } of targets) {
|
|
237
|
+
let servers = [];
|
|
238
|
+
try {
|
|
239
|
+
if (global) {
|
|
240
|
+
servers = await agent.getGlobalMCPServers();
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
servers = await agent.getMCPServers(cwd);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
// Agent may not have MCP config yet
|
|
248
|
+
}
|
|
249
|
+
const scope = global ? ' (global)' : '';
|
|
250
|
+
logger.subtitle(`${agent.name}${scope}:`);
|
|
251
|
+
if (servers.length === 0) {
|
|
252
|
+
logger.info(' No MCP servers configured');
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
for (const server of servers) {
|
|
256
|
+
const typeLabel = server.type.toUpperCase();
|
|
257
|
+
if (server.type === 'stdio' && server.command) {
|
|
258
|
+
logger.info(` ${cyan(server.name)} (${typeLabel})`);
|
|
259
|
+
logger.info(` Command: ${server.command} ${server.args?.join(' ') || ''}`);
|
|
260
|
+
}
|
|
261
|
+
else if (server.url) {
|
|
262
|
+
// Sanitize URL
|
|
263
|
+
let sanitized;
|
|
264
|
+
try {
|
|
265
|
+
const u = new URL(server.url);
|
|
266
|
+
u.username = '';
|
|
267
|
+
u.password = '';
|
|
268
|
+
u.search = '';
|
|
269
|
+
sanitized = u.toString();
|
|
270
|
+
}
|
|
271
|
+
catch {
|
|
272
|
+
sanitized = server.url.split('?')[0] || server.url;
|
|
273
|
+
}
|
|
274
|
+
logger.info(` ${cyan(server.name)} (${typeLabel})`);
|
|
275
|
+
logger.info(` URL: ${sanitized}`);
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
logger.info(` ${cyan(server.name)} (${typeLabel})`);
|
|
279
|
+
}
|
|
280
|
+
if (server.env && Object.keys(server.env).length > 0) {
|
|
281
|
+
const keys = Object.keys(server.env).join(', ');
|
|
282
|
+
logger.info(` Env: ${keys}`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
totalServers += servers.length;
|
|
287
|
+
logger.info('');
|
|
288
|
+
}
|
|
289
|
+
logger.info(`Total: ${totalServers} MCP server(s) across ${targets.length} agent(s)`);
|
|
290
|
+
}
|
|
291
|
+
catch (error) {
|
|
292
|
+
spinner.fail('Failed to list MCP servers');
|
|
293
|
+
logger.error(`${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
294
|
+
process.exit(1);
|
|
295
|
+
}
|
|
81
296
|
});
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
297
|
+
}
|
|
298
|
+
// ---------------------------------------------------------------------------
|
|
299
|
+
// Subcommand: mcp remove <name>
|
|
300
|
+
// ---------------------------------------------------------------------------
|
|
301
|
+
function registerRemoveCommand(mcp) {
|
|
302
|
+
mcp
|
|
303
|
+
.command('remove <name>')
|
|
304
|
+
.description('Remove an MCP server by name')
|
|
305
|
+
.option('--agent <agents...>', 'Target specific agent(s)')
|
|
306
|
+
.option('-g, --global', 'Remove from global configuration')
|
|
307
|
+
.action(async (name, options) => {
|
|
308
|
+
const cwd = process.cwd();
|
|
309
|
+
const agentManager = new AgentManager();
|
|
310
|
+
const isGlobal = !!options.global;
|
|
311
|
+
const spinner = ora(`Removing MCP server "${name}"...`).start();
|
|
312
|
+
try {
|
|
313
|
+
const targets = await resolveAgents(agentManager, options.agent, isGlobal, cwd);
|
|
314
|
+
if (targets.length === 0) {
|
|
315
|
+
spinner.warn('No target agents resolved');
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
let removedCount = 0;
|
|
319
|
+
let failedCount = 0;
|
|
320
|
+
for (const { agent, isGlobal: global } of targets) {
|
|
321
|
+
try {
|
|
322
|
+
let removed;
|
|
323
|
+
if (global) {
|
|
324
|
+
removed = await agent.removeGlobalMCPServer(name);
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
removed = await agent.removeMCPServer(cwd, name);
|
|
328
|
+
}
|
|
329
|
+
if (removed) {
|
|
330
|
+
removedCount++;
|
|
331
|
+
logger.info(` ${green('-')} ${agent.name}: removed "${name}"`);
|
|
332
|
+
}
|
|
333
|
+
else {
|
|
334
|
+
logger.info(` ${yellow('~')} ${agent.name}: "${name}" not found`);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
catch (err) {
|
|
338
|
+
failedCount++;
|
|
339
|
+
logger.info(` ${red('x')} ${agent.name}: ${err instanceof Error ? err.message : 'unknown error'}`);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
if (removedCount > 0) {
|
|
343
|
+
spinner.succeed(`Removed "${name}" from ${removedCount} agent(s)`);
|
|
344
|
+
}
|
|
345
|
+
else if (failedCount > 0) {
|
|
346
|
+
spinner.fail(`Failed to remove "${name}"`);
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
spinner.warn(`"${name}" was not found in any agent configuration`);
|
|
350
|
+
}
|
|
95
351
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if (typeof mcp === 'object') {
|
|
101
|
-
await installMCP(registry, mcp.name);
|
|
352
|
+
catch (error) {
|
|
353
|
+
spinner.fail(`Failed to remove MCP server "${name}"`);
|
|
354
|
+
logger.error(`${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
355
|
+
process.exit(1);
|
|
102
356
|
}
|
|
103
|
-
}
|
|
104
|
-
logger.success('✨ MCP installation complete!');
|
|
105
|
-
logger.info('Next steps:');
|
|
106
|
-
logger.info(' 1. Update your agents.md with MCP-specific instructions');
|
|
107
|
-
logger.info(' 2. Run `agentinit sync` to apply changes to agent configs');
|
|
357
|
+
});
|
|
108
358
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
359
|
+
// ---------------------------------------------------------------------------
|
|
360
|
+
// Subcommand: mcp verify
|
|
361
|
+
// ---------------------------------------------------------------------------
|
|
362
|
+
function registerVerifyCommand(mcp) {
|
|
363
|
+
mcp
|
|
364
|
+
.command('verify')
|
|
365
|
+
.description('Verify MCP server connectivity and capabilities')
|
|
366
|
+
.allowUnknownOption(true)
|
|
367
|
+
.option('--all', 'Verify all configured MCP servers')
|
|
368
|
+
.option('--name <name>', 'Verify a specific MCP server by name')
|
|
369
|
+
.option('--timeout <ms>', 'Connection timeout in milliseconds')
|
|
370
|
+
.action(async (options, command) => {
|
|
371
|
+
const cwd = process.cwd();
|
|
372
|
+
// Determine if raw MCP args were provided for direct verification
|
|
373
|
+
const allArgs = command.parent.parent.rawArgs;
|
|
374
|
+
const verifyIdx = allArgs.indexOf('verify');
|
|
375
|
+
const rawArgs = verifyIdx >= 0 ? allArgs.slice(verifyIdx + 1) : [];
|
|
376
|
+
const hasMcpArgs = rawArgs.some((a) => a.startsWith('--mcp-'));
|
|
377
|
+
const timeout = options.timeout ? parseInt(options.timeout, 10) : undefined;
|
|
378
|
+
// Validate mutually exclusive options
|
|
379
|
+
if (hasMcpArgs && (options.all || options.name)) {
|
|
380
|
+
logger.error('Cannot mix direct MCP server args (--mcp-*) with --all or --name');
|
|
381
|
+
process.exit(1);
|
|
382
|
+
}
|
|
383
|
+
if (options.all && options.name) {
|
|
384
|
+
logger.error('Cannot use --all and --name together');
|
|
385
|
+
process.exit(1);
|
|
386
|
+
}
|
|
387
|
+
// If no options at all, show usage
|
|
388
|
+
if (!hasMcpArgs && !options.all && !options.name) {
|
|
389
|
+
logger.info('Usage: agentinit mcp verify [options]');
|
|
390
|
+
logger.info('');
|
|
391
|
+
logger.info('Verify existing configurations:');
|
|
392
|
+
logger.info(' --all Verify all configured MCP servers');
|
|
393
|
+
logger.info(' --name <name> Verify a specific MCP server by name');
|
|
394
|
+
logger.info(` --timeout <ms> Connection timeout (default: ${DEFAULT_CONNECTION_TIMEOUT_MS})`);
|
|
395
|
+
logger.info('');
|
|
396
|
+
logger.info('Verify a server directly:');
|
|
397
|
+
logger.info(' --mcp-stdio <name> <command> Verify STDIO server');
|
|
398
|
+
logger.info(' --mcp-http <name> <url> Verify HTTP server');
|
|
399
|
+
logger.info(' --mcp-sse <name> <url> Verify SSE server');
|
|
400
|
+
logger.info('');
|
|
401
|
+
logger.info('Examples:');
|
|
402
|
+
logger.info(' agentinit mcp verify --all');
|
|
403
|
+
logger.info(' agentinit mcp verify --name exa');
|
|
404
|
+
logger.info(' agentinit mcp verify --mcp-stdio everything "npx -y @modelcontextprotocol/server-everything"');
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
let serversToVerify = [];
|
|
408
|
+
let serverSources = [];
|
|
409
|
+
const spinner = ora('Preparing verification...').start();
|
|
410
|
+
try {
|
|
411
|
+
if (hasMcpArgs) {
|
|
412
|
+
// Direct verification: parse --mcp-* args from the raw args
|
|
413
|
+
const mcpOnlyArgs = filterMcpArgs(rawArgs);
|
|
414
|
+
const parsed = MCPParser.parseArguments(mcpOnlyArgs);
|
|
415
|
+
if (parsed.servers.length === 0) {
|
|
416
|
+
spinner.warn('No MCP servers found in arguments');
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
serversToVerify = parsed.servers;
|
|
420
|
+
spinner.text = `Verifying ${serversToVerify.length} MCP server(s) from arguments...`;
|
|
421
|
+
}
|
|
422
|
+
else {
|
|
423
|
+
// Existing configuration verification
|
|
424
|
+
spinner.text = 'Detecting agents and MCP configurations...';
|
|
425
|
+
const agentManager = new AgentManager();
|
|
426
|
+
const detectedAgents = await agentManager.detectAgents(cwd);
|
|
427
|
+
if (detectedAgents.length === 0) {
|
|
428
|
+
spinner.warn('No AI coding agents detected in this project');
|
|
429
|
+
logger.info('Run `agentinit detect` to see which agents are supported');
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
// Collect servers from all detected agents
|
|
433
|
+
const allServers = [];
|
|
434
|
+
const allSources = [];
|
|
435
|
+
for (const { agent } of detectedAgents) {
|
|
436
|
+
try {
|
|
437
|
+
const servers = await agent.getMCPServers(cwd);
|
|
438
|
+
for (const server of servers) {
|
|
439
|
+
allServers.push(server);
|
|
440
|
+
allSources.push({
|
|
441
|
+
server,
|
|
442
|
+
agentName: agent.name,
|
|
443
|
+
configPath: agent.getNativeMcpPath(cwd),
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
catch {
|
|
448
|
+
// Agent may not have MCP config
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
if (allServers.length === 0) {
|
|
452
|
+
spinner.warn('No MCP servers found in any agent configuration');
|
|
453
|
+
logger.info('Use `agentinit mcp add` to add MCP servers');
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
if (options.all) {
|
|
457
|
+
serversToVerify = allServers;
|
|
458
|
+
serverSources = allSources;
|
|
459
|
+
}
|
|
460
|
+
else if (options.name) {
|
|
461
|
+
const matchName = options.name.toLowerCase();
|
|
462
|
+
serversToVerify = allServers.filter(s => s.name.toLowerCase() === matchName);
|
|
463
|
+
serverSources = allSources.filter(s => s.server.name.toLowerCase() === matchName);
|
|
464
|
+
if (serversToVerify.length === 0) {
|
|
465
|
+
spinner.fail(`MCP server "${options.name}" not found`);
|
|
466
|
+
logger.info('Available MCP servers:');
|
|
467
|
+
allServers.forEach(s => {
|
|
468
|
+
const src = allSources.find(x => x.server.name === s.name);
|
|
469
|
+
logger.info(` - ${s.name} (${s.type}) [${src?.agentName || 'unknown'}]`);
|
|
470
|
+
});
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
spinner.text = `Verifying ${serversToVerify.length} MCP server(s)...`;
|
|
475
|
+
}
|
|
476
|
+
// Run verification
|
|
477
|
+
await runVerification(serversToVerify, timeout, spinner, serverSources);
|
|
478
|
+
}
|
|
479
|
+
catch (error) {
|
|
480
|
+
spinner.fail('Verification failed');
|
|
481
|
+
if (error instanceof MCPParseError) {
|
|
482
|
+
logger.error(error.message);
|
|
483
|
+
}
|
|
484
|
+
else {
|
|
485
|
+
logger.error(`${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
486
|
+
}
|
|
487
|
+
process.exit(1);
|
|
488
|
+
}
|
|
489
|
+
});
|
|
118
490
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
491
|
+
// ---------------------------------------------------------------------------
|
|
492
|
+
// Shared verification helper
|
|
493
|
+
// ---------------------------------------------------------------------------
|
|
494
|
+
async function runVerification(servers, timeout, spinner, serverSources) {
|
|
495
|
+
const ownSpinner = spinner || ora(`Verifying ${servers.length} MCP server(s)...`).start();
|
|
496
|
+
const verifier = new MCPVerifier(timeout);
|
|
497
|
+
const results = await verifier.verifyServers(servers, timeout ? { timeout } : undefined);
|
|
498
|
+
const successCount = results.filter(r => r.status === 'success').length;
|
|
499
|
+
const errorCount = results.filter(r => r.status === 'error').length;
|
|
500
|
+
const timeoutCount = results.filter(r => r.status === 'timeout').length;
|
|
501
|
+
if (successCount === results.length) {
|
|
502
|
+
ownSpinner.succeed(`All ${results.length} MCP server(s) verified successfully!`);
|
|
503
|
+
}
|
|
504
|
+
else if (successCount > 0) {
|
|
505
|
+
ownSpinner.warn(`${successCount}/${results.length} MCP server(s) verified successfully`);
|
|
506
|
+
}
|
|
507
|
+
else {
|
|
508
|
+
ownSpinner.fail('Failed to verify any MCP servers');
|
|
509
|
+
}
|
|
125
510
|
logger.info('');
|
|
511
|
+
const formattedOutput = verifier.formatResults(results);
|
|
512
|
+
console.log(formattedOutput);
|
|
513
|
+
// Summary for multiple servers
|
|
514
|
+
if (results.length > 1) {
|
|
515
|
+
logger.info('Summary:');
|
|
516
|
+
logger.info(` Successful: ${successCount}`);
|
|
517
|
+
if (errorCount > 0)
|
|
518
|
+
logger.info(` Failed: ${errorCount}`);
|
|
519
|
+
if (timeoutCount > 0)
|
|
520
|
+
logger.info(` Timeout: ${timeoutCount}`);
|
|
521
|
+
logger.info('');
|
|
522
|
+
}
|
|
523
|
+
// Show source info for failed servers when we have sources
|
|
524
|
+
if (serverSources && serverSources.length > 0) {
|
|
525
|
+
const failed = results.filter(r => r.status !== 'success');
|
|
526
|
+
if (failed.length > 0) {
|
|
527
|
+
logger.info('Configuration Sources:');
|
|
528
|
+
for (const result of failed) {
|
|
529
|
+
const src = serverSources.find(s => s.server.name === result.server.name);
|
|
530
|
+
if (src) {
|
|
531
|
+
logger.info(` - ${result.server.name}: ${src.configPath} (${src.agentName})`);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
logger.info('');
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
// Troubleshooting tips for failures
|
|
538
|
+
if (successCount < results.length) {
|
|
539
|
+
logger.info('Troubleshooting:');
|
|
540
|
+
logger.info(' 1. Ensure MCP server packages are installed');
|
|
541
|
+
logger.info(' 2. Check environment variables are set correctly');
|
|
542
|
+
logger.info(' 3. Verify network connectivity for HTTP/SSE servers');
|
|
543
|
+
logger.info(' 4. Try increasing timeout with --timeout <ms>');
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
// ---------------------------------------------------------------------------
|
|
547
|
+
// Main registration
|
|
548
|
+
// ---------------------------------------------------------------------------
|
|
549
|
+
export function registerMcpCommand(program) {
|
|
550
|
+
const mcp = program
|
|
551
|
+
.command('mcp')
|
|
552
|
+
.description('Manage MCP server configurations');
|
|
553
|
+
registerAddCommand(mcp);
|
|
554
|
+
registerListCommand(mcp);
|
|
555
|
+
registerRemoveCommand(mcp);
|
|
556
|
+
registerVerifyCommand(mcp);
|
|
126
557
|
}
|
|
127
558
|
//# sourceMappingURL=mcp.js.map
|