66import type { CommandModule } from 'yargs' ;
77import { ConfigManager } from '../config/ConfigManager.js' ;
88import type { McpServerConfig } from '../config/types.js' ;
9+ import { McpRegistry } from '../mcp/McpRegistry.js' ;
10+ import { McpConnectionStatus } from '../mcp/types.js' ;
11+
12+ /**
13+ * 显示 MCP 命令的帮助信息
14+ */
15+ function showMcpHelp ( ) : void {
16+ console . log ( '\nblade mcp\n' ) ;
17+ console . log ( '管理 MCP 服务器\n' ) ;
18+ console . log ( 'Commands:' ) ;
19+ console . log ( ' blade mcp add <name> <commandOrUrl> [args...] 添加 MCP 服务器' ) ;
20+ console . log ( ' blade mcp remove <name> 删除 MCP 服务器 [aliases: rm]' ) ;
21+ console . log ( ' blade mcp list 列出所有 MCP 服务器并检查健康状态 [aliases: ls]' ) ;
22+ console . log ( ' blade mcp get <name> 获取服务器详情' ) ;
23+ console . log ( ' blade mcp add-json <name> <json> 从 JSON 字符串添加服务器' ) ;
24+ console . log ( ' blade mcp reset-project-choices 重置项目级 .mcp.json 确认记录\n' ) ;
25+ console . log ( 'Options:' ) ;
26+ console . log ( ' -h, --help 显示帮助信息 [boolean]\n' ) ;
27+ console . log ( 'Examples:' ) ;
28+ console . log ( ' blade mcp list' ) ;
29+ console . log ( ' blade mcp add github npx -y @modelcontextprotocol/server-github' ) ;
30+ console . log ( ' blade mcp add api --transport http http://localhost:3000' ) ;
31+ console . log ( ' blade mcp remove github\n' ) ;
32+ console . log ( '使用 blade mcp <command> --help 查看各子命令的详细帮助\n' ) ;
33+ }
934
1035// 工具函数:解析环境变量数组
1136function parseEnvArray ( envArray : string [ ] ) : Record < string , string > {
@@ -27,7 +52,7 @@ function parseHeaderArray(headerArray: string[]): Record<string, string> {
2752
2853// MCP Add 子命令
2954const mcpAddCommand : CommandModule = {
30- command : 'add <name> < commandOrUrl> [args...]' ,
55+ command : 'add <name> [ commandOrUrl] [args...]' ,
3156 describe : '添加 MCP 服务器' ,
3257 builder : ( yargs ) => {
3358 return yargs
@@ -39,7 +64,6 @@ const mcpAddCommand: CommandModule = {
3964 . positional ( 'commandOrUrl' , {
4065 type : 'string' ,
4166 describe : 'stdio: 命令 | http/sse: URL' ,
42- demandOption : true ,
4367 } )
4468 . positional ( 'args' , {
4569 type : 'string' ,
@@ -69,7 +93,11 @@ const mcpAddCommand: CommandModule = {
6993 } )
7094 . example ( [
7195 [
72- '$0 mcp add github npx -y @modelcontextprotocol/server-github -e GITHUB_TOKEN=xxx' ,
96+ '$0 mcp add github -- npx -y @modelcontextprotocol/server-github' ,
97+ 'Add stdio server (recommended)' ,
98+ ] ,
99+ [
100+ '$0 mcp add github npx @modelcontextprotocol/server-github -e GITHUB_TOKEN=xxx' ,
73101 'Add stdio server with env' ,
74102 ] ,
75103 [
@@ -81,7 +109,27 @@ const mcpAddCommand: CommandModule = {
81109 handler : async ( argv : any ) => {
82110 try {
83111 const configManager = ConfigManager . getInstance ( ) ;
84- const { name, commandOrUrl, args, transport, env, header, timeout } = argv ;
112+ let { name, commandOrUrl, args, transport, env, header, timeout } = argv ;
113+
114+ // 处理 -- 分隔符的情况
115+ // 当使用 `blade mcp add name -- command args` 时,yargs 会把 -- 后的内容放到 argv['--'] 中
116+ if ( argv [ '--' ] && argv [ '--' ] . length > 0 ) {
117+ // argv['--'] = ['command', ...args]
118+ commandOrUrl = argv [ '--' ] [ 0 ] ;
119+ args = argv [ '--' ] . slice ( 1 ) ;
120+ }
121+
122+ // 验证必需参数
123+ if ( ! name || ! commandOrUrl ) {
124+ console . error ( '❌ 缺少必需参数: name 和 commandOrUrl' ) ;
125+ console . log ( '\n💡 用法:' ) ;
126+ console . log ( ' blade mcp add <name> <command> [args...]' ) ;
127+ console . log ( ' blade mcp add <name> -- <command> [args...]' ) ;
128+ console . log ( '\n示例:' ) ;
129+ console . log ( ' blade mcp add github npx -y @modelcontextprotocol/server-github' ) ;
130+ console . log ( ' blade mcp add github -- npx -y @modelcontextprotocol/server-github' ) ;
131+ process . exit ( 1 ) ;
132+ }
85133
86134 const config : McpServerConfig = { type : transport } ;
87135
@@ -152,7 +200,7 @@ const mcpRemoveCommand: CommandModule = {
152200// MCP List 子命令
153201const mcpListCommand : CommandModule = {
154202 command : 'list' ,
155- describe : '列出所有 MCP 服务器 ' ,
203+ describe : '列出所有 MCP 服务器并检查健康状态 ' ,
156204 aliases : [ 'ls' ] ,
157205 handler : async ( ) => {
158206 try {
@@ -166,29 +214,59 @@ const mcpListCommand: CommandModule = {
166214 return ;
167215 }
168216
169- console . log ( 'MCP 服务器列表:\n' ) ;
170- for ( const [ name , config ] of Object . entries ( servers ) ) {
171- console . log ( `📦 ${ name } ` ) ;
172- console . log ( ` 类型: ${ config . type } ` ) ;
217+ console . log ( '检查 MCP 服务器健康状态...\n' ) ;
173218
174- if ( config . type === 'stdio' ) {
175- console . log ( ` 命令: ${ config . command } ${ config . args ?. join ( ' ' ) || '' } ` ) ;
176- if ( config . env && Object . keys ( config . env ) . length > 0 ) {
177- console . log ( ` 环境变量: ${ Object . keys ( config . env ) . join ( ', ' ) } ` ) ;
178- }
179- } else {
180- console . log ( ` URL: ${ config . url } ` ) ;
181- if ( config . headers ) {
182- console . log ( ` Headers: ${ Object . keys ( config . headers ) . length } 个` ) ;
219+ const mcpRegistry = McpRegistry . getInstance ( ) ;
220+
221+ // 尝试连接所有服务器
222+ const checkPromises = Object . entries ( servers ) . map ( async ( [ name , config ] ) => {
223+ try {
224+ // 检查服务器是否已注册
225+ let serverInfo = mcpRegistry . getServerStatus ( name ) ;
226+
227+ if ( ! serverInfo ) {
228+ // 如果未注册,先注册
229+ await mcpRegistry . registerServer ( name , config ) ;
230+ serverInfo = mcpRegistry . getServerStatus ( name ) ;
231+ } else if ( serverInfo . status === McpConnectionStatus . DISCONNECTED ) {
232+ // 如果已注册但未连接,尝试连接
233+ await mcpRegistry . connectServer ( name ) ;
183234 }
235+
236+ return { name, config, serverInfo } ;
237+ } catch ( error ) {
238+ return { name, config, serverInfo : null , error } ;
184239 }
240+ } ) ;
241+
242+ const results = await Promise . all ( checkPromises ) ;
243+
244+ // 显示结果
245+ for ( const { name, config, serverInfo, error } of results ) {
246+ const status = serverInfo ?. status || McpConnectionStatus . DISCONNECTED ;
247+ const statusSymbol = status === McpConnectionStatus . CONNECTED ? '✓' : '✗' ;
248+ const statusText = status === McpConnectionStatus . CONNECTED ? 'Connected' : 'Failed' ;
185249
186- if ( config . timeout ) {
187- console . log ( ` 超时: ${ config . timeout } ms` ) ;
250+ console . log ( `${ name } : ${ config . type === 'stdio' ? config . command : config . url } - ${ statusSymbol } ${ statusText } ` ) ;
251+
252+ if ( error && status !== McpConnectionStatus . CONNECTED ) {
253+ console . log ( ` 错误: ${ error instanceof Error ? error . message : String ( error ) } ` ) ;
188254 }
255+ }
256+
257+ console . log ( '' ) ;
189258
190- console . log ( '' ) ;
259+ // 断开所有服务器连接并清理
260+ for ( const { name } of results ) {
261+ try {
262+ await mcpRegistry . unregisterServer ( name ) ;
263+ } catch ( error ) {
264+ // 忽略断开连接时的错误
265+ }
191266 }
267+
268+ // 确保进程退出
269+ process . exit ( 0 ) ;
192270 } catch ( error ) {
193271 console . error (
194272 `❌ 列表获取失败: ${ error instanceof Error ? error . message : '未知错误' } `
@@ -309,16 +387,23 @@ export const mcpCommands: CommandModule = {
309387 . command ( mcpGetCommand )
310388 . command ( mcpAddJsonCommand )
311389 . command ( mcpResetProjectChoicesCommand )
312- . demandCommand ( 1 , '请指定子命令' )
313- . help ( )
314- . example ( [
315- [ '$0 mcp list' , 'List all MCP servers' ] ,
316- [ '$0 mcp add github npx -y @modelcontextprotocol/server-github' , 'Add stdio server' ] ,
317- [ '$0 mcp add api --transport http http://localhost:3000' , 'Add HTTP server' ] ,
318- [ '$0 mcp remove github' , 'Remove server' ] ,
319- ] ) ;
390+ . demandCommand ( 0 ) // 允许不传子命令
391+ . help ( false ) // 禁用自动帮助,我们自己处理
392+ . option ( 'help' , {
393+ alias : 'h' ,
394+ type : 'boolean' ,
395+ describe : '显示帮助信息' ,
396+ } ) ;
320397 } ,
321- handler : ( ) => {
322- // 如果没有子命令,yargs 会自动显示帮助
398+ handler : ( argv : any ) => {
399+ // 检查是否有子命令
400+ const subcommands = [ 'add' , 'remove' , 'list' , 'ls' , 'get' , 'add-json' , 'reset-project-choices' ] ;
401+ const hasSubcommand = argv . _ . some ( ( arg : string ) => subcommands . includes ( arg ) ) ;
402+
403+ // 如果没有子命令或者显式请求帮助,显示帮助信息
404+ if ( ! hasSubcommand || argv . help ) {
405+ showMcpHelp ( ) ;
406+ process . exit ( 0 ) ;
407+ }
323408 } ,
324409} ;
0 commit comments