Skip to content

Commit d828c36

Browse files
jakemac53Commit Queue
authored andcommitted
Add a dart mcp-server command per go/dart-mcp-server-release-plan.
- Adds `dart_mcp` and `dart_mcp_server` as DEPS - Build an AOT snapshot for the dart_mcp_server executable - Add top level `mcp-server` command to dartdev (hidden). - I also did add an `--experimental-mcp-server` flag which is required for this command to actually work. We had initially discussed not doing this due to complexity but I was able to keep it completely scoped to just this command. I can remove it if there are strong opinions though. Change-Id: I737a5625507f69a904ccd1012682764eb360a2c2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/430900 Reviewed-by: Siva Annamalai <[email protected]> Reviewed-by: Ben Konyi <[email protected]> Commit-Queue: Jake Macdonald <[email protected]>
1 parent f3a4e5b commit d828c36

File tree

7 files changed

+121
-0
lines changed

7 files changed

+121
-0
lines changed

DEPS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ vars = {
129129
### /third_party/pkg dependencies
130130
# 'tools/rev_sdk_deps.dart' will rev pkg dependencies to their latest; put an
131131
# EOL comment after a dependency to instead pin at the current revision.
132+
"ai_rev": "93a9191b6eed79d24fc5d3ec9b514f71c888fc41",
132133
"core_rev": "635dfa32c261ba078438b74de397f2207904ca78", # https://github.com/dart-lang/core/pull/734
133134
"dartdoc_rev": "e38f392163a4738a21024acd370d104e0efe72f0",
134135
"ecosystem_rev": "815d4ba2e7d11f8695a26f6cbe1262e3b8ff8d0d",
@@ -327,6 +328,8 @@ deps = {
327328
Var('chromium_git') + '/external/github.com/mdn/browser-compat-data' +
328329
"@" + Var("browser-compat-data_tag"),
329330

331+
Var("dart_root") + "/third_party/pkg/ai":
332+
Var("dart_git") + "ai.git" + "@" + Var("ai_rev"),
330333
Var("dart_root") + "/third_party/pkg/core":
331334
Var("dart_git") + "core.git" + "@" + Var("core_rev"),
332335
Var("dart_root") + "/third_party/pkg/dart_style":

pkg/dartdev/lib/dartdev.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import 'src/commands/build.dart';
2020
import 'src/commands/compilation_server.dart';
2121
import 'src/commands/compile.dart';
2222
import 'src/commands/create.dart';
23+
import 'src/commands/dart_mcp_server.dart';
2324
import 'src/commands/debug_adapter.dart';
2425
import 'src/commands/development_service.dart';
2526
import 'src/commands/devtools.dart';
@@ -118,6 +119,7 @@ class DartdevRunner extends CommandRunner<int> {
118119
addCommand(FormatCommand(verbose: verbose));
119120
addCommand(InfoCommand(verbose: verbose));
120121
addCommand(LanguageServerCommand(verbose: verbose));
122+
addCommand(DartMCPServerCommand(verbose: verbose));
121123
addCommand(pubCommand(isVerbose: () => verbose));
122124
addCommand(RunCommand(
123125
verbose: verbose,
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:async';
6+
7+
import '../core.dart';
8+
import '../sdk.dart';
9+
import '../vm_interop_handler.dart';
10+
11+
class DartMCPServerCommand extends DartdevCommand {
12+
static const String cmdName = 'mcp-server';
13+
14+
static const String cmdDescription = '''
15+
A stdio based Model Context Protocol (MCP) server to aid in Dart and Flutter development.
16+
17+
EXPERIMENTAL: This tool may change dramatically or disappear at any time.''';
18+
19+
static const _forceRootsFallbackFlag = 'force-roots-fallback';
20+
static const _experimentFlag = 'experimental-mcp-server';
21+
22+
DartMCPServerCommand({bool verbose = false})
23+
: super(cmdName, cmdDescription, verbose, hidden: true) {
24+
argParser
25+
..addFlag(
26+
_forceRootsFallbackFlag,
27+
negatable: true,
28+
defaultsTo: false,
29+
help:
30+
'Forces a behavior for project roots which uses MCP tools instead '
31+
'of the native MCP roots. This can be helpful for clients like '
32+
'Cursor which claim to have roots support but do not actually '
33+
'support it.',
34+
)
35+
..addFlag(_experimentFlag,
36+
defaultsTo: false,
37+
help: 'A required flag in order to use this command. Passing this '
38+
'flag is an acknowledgement that you understand it is an '
39+
'experimental feature with no stability guarantees.');
40+
}
41+
42+
@override
43+
Future<int> run() async {
44+
final args = argResults!;
45+
if (!args.flag(_experimentFlag)) {
46+
log.stderr('Missing required flag --$_experimentFlag\n\n$usage');
47+
return 64;
48+
}
49+
try {
50+
VmInteropHandler.run(
51+
sdk.dartAotRuntime,
52+
[
53+
sdk.dartMCPServerAotSnapshot,
54+
if (args.flag(_forceRootsFallbackFlag)) '--$_forceRootsFallbackFlag'
55+
],
56+
useExecProcess: true,
57+
);
58+
return 0;
59+
} catch (e, st) {
60+
log.stderr('Error: launching Dart MCP server failed');
61+
log.stderr(e.toString());
62+
if (verbose) {
63+
log.stderr(st.toString());
64+
}
65+
return 255;
66+
}
67+
}
68+
}

pkg/dartdev/lib/src/sdk.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ class Sdk {
102102
'dart2wasm_product.snapshot',
103103
);
104104

105+
String get dartMCPServerAotSnapshot => _snapshotPathFor(
106+
'dart_mcp_server_aot.dart.snapshot',
107+
);
108+
105109
String get ddsSnapshot => _snapshotPathFor(
106110
'dds.dart.snapshot',
107111
);

pubspec.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ dependency_overrides:
143143
path: third_party/pkg/tools/pkgs/csslib
144144
dart_flutter_team_lints:
145145
path: third_party/pkg/ecosystem/pkgs/dart_flutter_team_lints
146+
dart_mcp:
147+
path: third_party/pkg/ai/pkgs/dart_mcp
148+
dart_mcp_server:
149+
path: third_party/pkg/ai/pkgs/dart_mcp_server
146150
dart_style:
147151
path: third_party/pkg/dart_style
148152
dartdoc:
@@ -221,6 +225,8 @@ dependency_overrides:
221225
path: third_party/pkg/tools/pkgs/pool
222226
protobuf:
223227
path: third_party/pkg/protobuf/protobuf
228+
process:
229+
path: third_party/pkg/tools/pkgs/process
224230
protobuf_benchmarks:
225231
path: third_party/pkg/protobuf/benchmarks
226232
protoc_plugin:
@@ -257,6 +263,8 @@ dependency_overrides:
257263
path: third_party/pkg/tools/pkgs/stack_trace
258264
stream_channel:
259265
path: third_party/pkg/tools/pkgs/stream_channel
266+
stream_transform:
267+
path: third_party/pkg/tools/pkgs/stream_transform
260268
string_scanner:
261269
path: third_party/pkg/tools/pkgs/string_scanner
262270
swift2objc:

sdk/BUILD.gn

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ if (dart_target_arch != "ia32" && dart_target_arch != "x86") {
151151
"../utils/dtd:dtd_aot",
152152
"dart_tooling_daemon_aot",
153153
],
154+
[
155+
"dart_mcp_server_aot_product",
156+
"../utils/dart_mcp_server:dart_mcp_server_aot",
157+
"dart_mcp_server_aot",
158+
],
154159
]
155160
} else {
156161
_platform_sdk_snapshots += [

utils/dart_mcp_server/BUILD.gn

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
# for details. All rights reserved. Use of this source code is governed by a
3+
# BSD-style license that can be found in the LICENSE file.
4+
5+
import("../../runtime/runtime_args.gni")
6+
import("../aot_snapshot.gni")
7+
8+
group("dart_mcp_server_aot") {
9+
public_deps = [
10+
":dart_mcp_server_aot_product_snapshot",
11+
":dart_mcp_server_aot_snapshot",
12+
]
13+
}
14+
15+
aot_snapshot("dart_mcp_server_aot_snapshot") {
16+
main_dart = "../../third_party/pkg/ai/pkgs/dart_mcp_server/bin/main.dart"
17+
output = "$root_gen_dir/dart_mcp_server_aot.dart.snapshot"
18+
}
19+
20+
aot_snapshot("dart_mcp_server_aot_product_snapshot") {
21+
main_dart = "../../third_party/pkg/ai/pkgs/dart_mcp_server/bin/main.dart"
22+
output = "$root_gen_dir/dart_mcp_server_aot_product.dart.snapshot"
23+
24+
# dartaotruntime has dart_product_config applied to it,
25+
# so it is built in product mode in both release and
26+
# product builds, and is only built in debug mode in debug
27+
# builds. The following line ensures that the dartaotruntime
28+
# and dart_mcp_server_aot snapshot in an SDK build are
29+
# always compatible with each other.
30+
force_product_mode = !dart_debug
31+
}

0 commit comments

Comments
 (0)