11import 'dart:async' ;
2+ import 'dart:io' show stderr;
23
34import 'package:args/command_runner.dart' ;
45import 'package:dart_mcp/server.dart' ;
@@ -20,8 +21,7 @@ final class VeryGoodMCPServer extends MCPServer with ToolsSupport {
2021 required StreamChannel <String > channel,
2122 Logger ? logger,
2223 VeryGoodCommandRunner ? commandRunner,
23- }) : _logger = logger ?? Logger (),
24- _commandRunner =
24+ }) : _commandRunner =
2525 commandRunner ?? VeryGoodCommandRunner (logger: logger ?? Logger ()),
2626 super .fromStreamChannel (
2727 channel,
@@ -34,8 +34,6 @@ final class VeryGoodMCPServer extends MCPServer with ToolsSupport {
3434 'for creating and managing Dart/Flutter projects.' ,
3535 );
3636
37- final Logger _logger;
38-
3937 final VeryGoodCommandRunner _commandRunner;
4038
4139 @override
@@ -414,52 +412,19 @@ Only one value can be selected.
414412 Future <CallToolResult > _handleCreate (CallToolRequest request) async {
415413 final args = request.arguments ?? {};
416414 final cliArgs = _parseCreate (args);
417- final exitCode = await _runCommand (cliArgs);
418-
419- return CallToolResult (
420- content: [
421- TextContent (
422- text: exitCode == ExitCode .success.code
423- ? 'Project created successfully'
424- : 'Failed to create project' ,
425- ),
426- ],
427- isError: exitCode != ExitCode .success.code,
428- );
415+ return _runToolCommand (cliArgs, toolName: 'create' );
429416 }
430417
431418 Future <CallToolResult > _handleTest (CallToolRequest request) async {
432419 final args = request.arguments ?? {};
433420 final cliArgs = _parseTest (args);
434- final exitCode = await _runCommand (cliArgs);
435-
436- return CallToolResult (
437- content: [
438- TextContent (
439- text: exitCode == ExitCode .success.code
440- ? 'Tests completed successfully'
441- : 'Tests failed' ,
442- ),
443- ],
444- isError: exitCode != ExitCode .success.code,
445- );
421+ return _runToolCommand (cliArgs, toolName: 'test' );
446422 }
447423
448424 Future <CallToolResult > _handlePackagesGet (CallToolRequest request) async {
449425 final args = request.arguments ?? {};
450426 final cliArgs = _parsePackagesGet (args);
451- final exitCode = await _runCommand (cliArgs);
452-
453- return CallToolResult (
454- content: [
455- TextContent (
456- text: exitCode == ExitCode .success.code
457- ? 'Packages retrieved successfully'
458- : 'Failed to get packages' ,
459- ),
460- ],
461- isError: exitCode != ExitCode .success.code,
462- );
427+ return _runToolCommand (cliArgs, toolName: 'packages get' );
463428 }
464429
465430 Future <CallToolResult > _handlePackagesCheck (CallToolRequest request) async {
@@ -483,37 +448,57 @@ Only one value can be selected.
483448 }
484449
485450 final cliArgs = _parsePackagesCheck (args);
486- final exitCode = await _runCommand (cliArgs);
487-
488- return CallToolResult (
489- content: [
490- TextContent (
491- text: exitCode == ExitCode .success.code
492- ? 'Package license check completed successfully'
493- : 'Package license check failed' ,
494- ),
495- ],
496- isError: exitCode != ExitCode .success.code,
497- );
451+ return _runToolCommand (cliArgs, toolName: 'packages check licenses' );
498452 }
499453
500- /// Runs CLI commands through the command runner.
501- /// Commands parse their own arguments using their argParser.
502- Future <int > _runCommand (List <String > args) async {
503- try {
504- _logger.detail ('Running: very_good ${args .join (' ' )}' );
454+ /// Runs a CLI command and returns a [CallToolResult] with descriptive
455+ /// error messages including the command that was run and the exit code.
456+ Future <CallToolResult > _runToolCommand (
457+ List <String > args, {
458+ required String toolName,
459+ }) async {
460+ final commandString = 'very_good ${args .join (' ' )}' ;
505461
462+ try {
506463 final exitCode = await _commandRunner.run (args);
507464
508- return exitCode;
465+ if (exitCode == ExitCode .success.code) {
466+ return CallToolResult (
467+ content: [
468+ TextContent (text: '"$toolName " completed successfully.' ),
469+ ],
470+ isError: false ,
471+ );
472+ }
473+
474+ final message =
475+ '"$toolName " failed with exit code $exitCode .\n '
476+ 'Command: $commandString ' ;
477+ stderr.writeln ('[very_good_mcp] $message ' );
478+ return CallToolResult (
479+ content: [TextContent (text: message)],
480+ isError: true ,
481+ );
509482 } on UsageException catch (e) {
510- _logger.err ('Usage error: ${e .message }' );
511- return ExitCode .usage.code;
483+ final message =
484+ '"$toolName " usage error: ${e .message }\n '
485+ 'Command: $commandString ' ;
486+ stderr.writeln ('[very_good_mcp] $message ' );
487+ return CallToolResult (
488+ content: [TextContent (text: message)],
489+ isError: true ,
490+ );
512491 } on Exception catch (e, stackTrace) {
513- _logger
514- ..err ('Command error: $e ' )
515- ..err ('Stack trace: $stackTrace ' );
516- return ExitCode .software.code;
492+ final message =
493+ '"$toolName " threw an exception: $e \n '
494+ 'Command: $commandString ' ;
495+ stderr
496+ ..writeln ('[very_good_mcp] $message ' )
497+ ..writeln ('[very_good_mcp] Stack trace: $stackTrace ' );
498+ return CallToolResult (
499+ content: [TextContent (text: message)],
500+ isError: true ,
501+ );
517502 }
518503 }
519504}
0 commit comments