Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
1832e66
feat: init mcp
ryzizub Oct 3, 2025
50fc6d2
refactor: refactored MCP server to use VeryGoodCommandRunner and mino…
PabloTortosaLopez Nov 13, 2025
5a7dcfb
chore: expand tool descriptions and input schema details
PabloTortosaLopez Nov 14, 2025
75499d6
feat: fixed create tool description and arguments
RuiMiguel Nov 14, 2025
82a42e5
feat: fixed test tool description and arguments
RuiMiguel Nov 14, 2025
22acc65
fix: changed some create arguments descriptions
RuiMiguel Nov 14, 2025
0901974
fix: improved some descriptions
RuiMiguel Nov 17, 2025
b2a8709
fix: doc and fix tests
RuiMiguel Nov 17, 2025
ed8d211
fix: test coverage for mcp_command
RuiMiguel Nov 17, 2025
21f881f
fix: test coverage for mcp_command
RuiMiguel Nov 17, 2025
2a79d5e
fix: tests and coverage for mcp_server
RuiMiguel Nov 17, 2025
889189e
fix: exclude-covereage fix and test coverage
RuiMiguel Nov 17, 2025
886b3e5
fix: fixed exclude_coverage schema
RuiMiguel Nov 17, 2025
78f5138
chore: removed unreachable exception blocks in each handle command
PabloTortosaLopez Nov 18, 2025
dcf3649
refactor: extract cliArgs to improve readability
PabloTortosaLopez Nov 18, 2025
2015745
Merge branch 'main' into feat/mcp
PabloTortosaLopez Nov 18, 2025
e97f60d
chore: rename packages_check tool to packages_check_licenses and mino…
PabloTortosaLopez Nov 18, 2025
9431269
chore: remove unnecessary comments in mcp_server.dart
PabloTortosaLopez Nov 18, 2025
6bc56e1
chore: remove unnecessary comments about stream_channel dependency
PabloTortosaLopez Nov 18, 2025
731ac35
chore: update MCP tool names and links in README
PabloTortosaLopez Nov 18, 2025
546b070
chore: added experimental warning for mcp at README
RuiMiguel Nov 19, 2025
f29cb5e
fix: added experimental warning message to cli help
RuiMiguel Nov 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,26 @@ very_good packages check licenses --forbidden="unknown"
very_good packages check licenses --dependency-type="direct-main,transitive"
```

### [`very_good mcp`](https://cli.vgv.dev/docs/commands/mcp)

Start the MCP (Model Context Protocol) server for AI assistant integration.

> ℹ️ **Experimental**
> This command relies on the [Dart MCP Server](https://docs.flutter.dev/ai/mcp-server). This is an experimental package and may change or become unstable without notice. Use it with caution at your own risk.

```sh
# Start the MCP server
very_good mcp
```

The MCP server exposes Very Good CLI functionality through the Model Context Protocol, allowing AI assistants to interact with the CLI programmatically. This enables automated project creation, testing, and package management through MCP-compatible tools.

**Available MCP Tools:**
- `create`: Create new Dart/Flutter projects (https://cli.vgv.dev/docs/category/templates)
- `tests`: Run tests with optional coverage and optimization (https://cli.vgv.dev/docs/commands/test)
- `packages_check_licenses`: Check packages for issues and licenses (https://cli.vgv.dev/docs/commands/check_licenses)
- `packages_get`: Get package information and dependencies (https://cli.vgv.dev/docs/commands/get_pkgs)

### [`very_good --help`](https://cli.vgv.dev/docs/overview)

See the complete list of commands and usage information.
Expand All @@ -194,6 +214,7 @@ Global options:
Available commands:
create very_good create <subcommand> <project-name> [arguments]
Creates a new very good project in the specified directory.
mcp Start the MCP (Model Context Protocol) server. WARNING: This is an experimental package and may change or become unstable without notice. Use it with caution at your own risk.
packages Command for managing packages.
test Run tests in a Dart or Flutter project.
update Update Very Good CLI.
Expand Down
Empty file modified bin/very_good.dart
100644 → 100755
Empty file.
2 changes: 2 additions & 0 deletions lib/src/command_runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:pub_updater/pub_updater.dart';
import 'package:universal_io/io.dart';
import 'package:very_good_cli/src/commands/commands.dart';
import 'package:very_good_cli/src/logger_extension.dart';
import 'package:very_good_cli/src/mcp/mcp.dart';
import 'package:very_good_cli/src/version.dart';

/// The package name.
Expand Down Expand Up @@ -37,6 +38,7 @@ class VeryGoodCommandRunner extends CompletionCommandRunner<int> {
addCommand(TestCommand(logger: _logger));
addCommand(UpdateCommand(logger: _logger, pubUpdater: pubUpdater));
addCommand(DartCommand(logger: _logger));
addCommand(MCPCommand(logger: _logger));
}

/// Standard timeout duration for the CLI.
Expand Down
2 changes: 2 additions & 0 deletions lib/src/mcp/mcp.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export 'mcp_command.dart';
export 'mcp_server.dart';
104 changes: 104 additions & 0 deletions lib/src/mcp/mcp_command.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import 'dart:async';
import 'dart:io';

import 'package:args/command_runner.dart';
import 'package:dart_mcp/server.dart';
import 'package:dart_mcp/stdio.dart';
import 'package:mason/mason.dart';
import 'package:stream_channel/stream_channel.dart';
import 'package:very_good_cli/src/mcp/mcp_server.dart';

/// Type definition for a factory that creates a [VeryGoodMCPServer].
typedef ServerFactory =
MCPServer Function({
required StreamChannel<String> channel,
required Logger logger,
});

/// Factory function to create a [StreamChannel] from input and output streams.
typedef ChannelFactory = StreamChannel<String> Function();

// Private default implementation for the channel factory
StreamChannel<String> _defaultChannelFactory() {
return stdioChannel(input: stdin, output: stdout);
}

/// {@template mcp_command}
/// `very_good mcp` command starts the MCP (Model Context Protocol) server.
/// {@endtemplate}
class MCPCommand extends Command<int> {
/// {@macro mcp_command}
MCPCommand({
Logger? logger,
ChannelFactory? channelFactory,
ServerFactory? serverFactory,
}) : _logger = logger ?? Logger(),
_channelFactory = channelFactory ?? _defaultChannelFactory,
_serverFactory = serverFactory ?? VeryGoodMCPServer.new;

/// The [name] of the command. But static.
static const String commandName = 'mcp';

@override
String get description => '''
Start the MCP (Model Context Protocol) server. WARNING: This is an experimental package and may change or become unstable without notice. Use it with caution at your own risk.''';

@override
String get name => commandName;

final Logger _logger;

final ChannelFactory _channelFactory;

final ServerFactory _serverFactory;

@override
Future<int> run() async {
try {
_logger
..info('Starting Very Good CLI MCP Server...')
..info(
'Server will listen on stdin/stdout for MCP protocol messages',
);

// Create a channel from stdin/stdout using the stdio helper
final channel = _channelFactory();

// Create and start the MCP server
final server = _serverFactory(
channel: channel,
logger: _logger,
);

_logger
..info('MCP Server started successfully')
..info('Available tools:')
..info('''
- create: Create a very good Dart or Flutter project in seconds based on the provided template. Each template has a corresponding sub-command.''')
..info(' - test: Run tests in a Dart or Flutter project.')
..info(
'''
- packages_get: Install or update Dart/Flutter package dependencies.
Use after creating a project or modifying pubspec.yaml.
Supports recursive installation and package exclusion.''',
)
..info(
'''
- packages_check_licenses: Verify package licenses for compliance and validation in a Dart or Flutter project.
Identifies license types (MIT, BSD, Apache, etc.) for all
dependencies. Use to ensure license compatibility.''',
);

// Wait for the server to complete
// (this will block until the connection is closed)
await server.done;

return ExitCode.success.code;
} on Exception catch (e, stackTrace) {
_logger
..err('Failed to start MCP server: $e')
..err('Stack trace: $stackTrace');
return ExitCode.software.code;
}
}
}
Loading