Skip to content

Commit 3ab32d1

Browse files
authored
feat: implement version check and update command (#56)
- Add `update` command to CLI - Add version check logic using `pub_updater` - Update `mcp_dart` binary to include version check - Fix usage of global `pubspec` in tests - Update tests for create, doctor, and serve commands - Update CHANGELOG.md, README.md, and example.md
1 parent 27fa607 commit 3ab32d1

14 files changed

Lines changed: 266 additions & 25 deletions

packages/mcp_dart_cli/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1+
## 0.1.5
2+
3+
- **`update` command**:
4+
- Update the CLI to the latest version via `mcp_dart update`.
5+
- Automatic update checks on command execution.
6+
17
## 0.1.4
28

9+
310
- **`create` command**:
411
- Improved package name inference when creating a project from a path (e.g. `mcp_dart create ./my-project`).
512
- Internal refactoring for better testability.

packages/mcp_dart_cli/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ mcp_dart create <project_name> --template https://github.com/leehack/mcp_dart/tr
5252
- `serve`: Runs the MCP server in the current directory.
5353
- `doctor`: Checks the project for common issues and verifies connectivity.
5454
- `inspect`: Interacts with an MCP server (local or external).
55+
- `update`: Updates the CLI to the latest version.
5556

5657
### Doctor
5758

@@ -137,6 +138,14 @@ mcp_dart serve
137138
- `--port` (`-p`): Port for HTTP transport. Defaults to `3000`.
138139
- `--watch`: Restart the server on file changes.
139140

141+
### Update
142+
143+
Updates the CLI to the latest version.
144+
145+
```bash
146+
mcp_dart update
147+
```
148+
140149
## Running Tests
141150

142151
To run the tests for this package:

packages/mcp_dart_cli/bin/mcp_dart.dart

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,16 @@ import 'package:mcp_dart_cli/src/create_command.dart';
55
import 'package:mcp_dart_cli/src/serve_command.dart';
66
import 'package:mcp_dart_cli/src/doctor_command.dart';
77
import 'package:mcp_dart_cli/src/inspect_command.dart';
8+
import 'package:mcp_dart_cli/src/update_command.dart';
9+
import 'package:mcp_dart_cli/src/version.dart';
10+
import 'package:mcp_dart_cli/src/version_check.dart';
811

912
void main(List<String> arguments) async {
13+
if (arguments.contains('--version') || arguments.contains('-v')) {
14+
stdout.writeln(packageVersion);
15+
exit(0);
16+
}
17+
1018
final logger = Logger();
1119
final runner = CommandRunner<int>(
1220
'mcp_dart',
@@ -15,10 +23,14 @@ void main(List<String> arguments) async {
1523
..addCommand(CreateCommand())
1624
..addCommand(ServeCommand())
1725
..addCommand(DoctorCommand())
18-
..addCommand(InspectCommand(logger: logger));
26+
..addCommand(InspectCommand(logger: logger))
27+
..addCommand(UpdateCommand(logger: logger));
1928

2029
try {
2130
final exitCode = await runner.run(arguments);
31+
if (!arguments.contains('update')) {
32+
await checkForUpdate(logger);
33+
}
2234
exit(exitCode ?? 0);
2335
} catch (e) {
2436
stderr.writeln(e);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
concurrency: 1

packages/mcp_dart_cli/example/example.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,11 @@ mcp_dart inspect --url http://localhost:3000/mcp
147147
```bash
148148
mcp_dart inspect --env API_KEY=your_key --env DEBUG=true -- python my_server.py
149149
```
150+
151+
## Updating the CLI
152+
153+
Update to the latest version of `mcp_dart_cli`:
154+
155+
```bash
156+
mcp_dart update
157+
```
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import 'package:args/command_runner.dart';
2+
import 'package:mason_logger/mason_logger.dart';
3+
import 'package:mcp_dart_cli/src/version.dart';
4+
import 'package:pub_updater/pub_updater.dart';
5+
6+
/// {@template update_command}
7+
/// A command which updates the CLI.
8+
/// {@endtemplate}
9+
class UpdateCommand extends Command<int> {
10+
/// {@macro update_command}
11+
UpdateCommand({
12+
required Logger logger,
13+
PubUpdater? pubUpdater,
14+
}) : _logger = logger,
15+
_pubUpdater = pubUpdater ?? PubUpdater();
16+
17+
final Logger _logger;
18+
final PubUpdater _pubUpdater;
19+
20+
@override
21+
String get description => 'Update the CLI.';
22+
23+
@override
24+
String get name => 'update';
25+
26+
@override
27+
Future<int> run() async {
28+
final updateCheckProgress = _logger.progress('Checking for updates');
29+
late final String latestVersion;
30+
try {
31+
latestVersion = await _pubUpdater.getLatestVersion('mcp_dart_cli');
32+
} catch (error) {
33+
updateCheckProgress.fail();
34+
_logger.err('$error');
35+
return ExitCode.software.code;
36+
}
37+
updateCheckProgress.complete('Checked for updates');
38+
39+
final isUpToDate = packageVersion == latestVersion;
40+
if (isUpToDate) {
41+
_logger.info('CLI is already at the latest version.');
42+
return ExitCode.success.code;
43+
}
44+
45+
final updateProgress = _logger.progress('Updating to $latestVersion');
46+
try {
47+
await _pubUpdater.update(packageName: 'mcp_dart_cli');
48+
} catch (error) {
49+
updateProgress.fail();
50+
_logger.err('$error');
51+
return ExitCode.software.code;
52+
}
53+
updateProgress.complete('Updated to $latestVersion');
54+
55+
return ExitCode.success.code;
56+
}
57+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
const packageVersion = '0.1.5';
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import 'package:mason_logger/mason_logger.dart';
2+
import 'package:pub_updater/pub_updater.dart';
3+
4+
import 'version.dart';
5+
6+
Future<void> checkForUpdate(Logger logger) async {
7+
try {
8+
final pubUpdater = PubUpdater();
9+
final isUpToDate = await pubUpdater.isUpToDate(
10+
packageName: 'mcp_dart_cli',
11+
currentVersion: packageVersion,
12+
);
13+
if (!isUpToDate) {
14+
final latestVersion = await pubUpdater.getLatestVersion('mcp_dart_cli');
15+
logger.info(
16+
'New version of mcp_dart_cli available! ($packageVersion -> $latestVersion)\n'
17+
'Run ${cyan.wrap('dart pub global activate mcp_dart_cli')} to update.',
18+
);
19+
}
20+
} catch (_) {
21+
// Suppress update check errors
22+
}
23+
}

packages/mcp_dart_cli/pubspec.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: mcp_dart_cli
22
description: CLI for Model Context Protocol (MCP) servers in Dart.
3-
version: 0.1.4
3+
version: 0.1.5
44
repository: https://github.com/leehack/mcp_dart
55

66
environment:
@@ -17,6 +17,7 @@ dependencies:
1717
mcp_dart: ^1.1.2
1818
mason_logger: ^0.3.3
1919
meta: ^1.17.0
20+
pub_updater: ^0.5.0
2021

2122
dependency_overrides:
2223
mcp_dart:

packages/mcp_dart_cli/test/src/create_command_test.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ void main() {
5252
logger = MockLogger();
5353
generator = MockMasonGenerator();
5454
tempDir = Directory.systemTemp.createTempSync('mcp_dart_cli_test');
55+
tempDir = Directory(tempDir.resolveSymbolicLinksSync());
5556
originalCwd = Directory.current;
5657
Directory.current = tempDir;
5758

0 commit comments

Comments
 (0)