Skip to content

add a CI check that the readme file is up-to-date #192

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 13 additions & 0 deletions .github/workflows/dart_mcp_server.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,16 @@ jobs:
if: ${{ matrix.flutterSdk == 'master' }}

- run: dart test

readme:
runs-on: ubuntu-latest
strategy:
fail-fast: false
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c

- run: dart pub get
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could just merge this into the job above to avoid the extra setup work 🤷‍♂️ . This repo isn't large enough to really need multiple jobs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kept this separate since this above job was doing more than we need here (using the flutter sdk instead of the dart sdk, ...).

- run: dart tool/update_readme.dart
# If this fails, you need to run 'dart tool/update_readme.dart'.
- run: git diff --exit-code
47 changes: 27 additions & 20 deletions pkgs/dart_mcp_server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,24 +144,31 @@ For more information, see the official VS Code documentation for

## Tools

| Tool Name | Feature Group | Description |
<!-- run 'dart tool/update_readme.dart' to update -->

<!-- generated -->

| Tool Name | Title | Description |
| --- | --- | --- |
| `analyze_files` | `static analysis` | Analyzes the entire project for errors. |
| `signature_help` | `static_analysis` | Gets signature information for usage at a given cursor position. |
| `hover` | `static_analysis` | Gets the hover information for a given cursor position. |
| `resolve_workspace_symbol` | `static analysis` | Look up a symbol or symbols in all workspaces by name. |
| `dart_fix` | `static tool` | Runs `dart fix --apply` for the given project roots. |
| `dart_format` | `static tool` | Runs `dart format .` for the given project roots. |
| `pub` | `static tool` | Runs a `dart pub` command for the given project roots. |
| `pub_dev_search` | `package search` | Searches pub.dev for packages relevant to a given search query. |
| `get_runtime_errors` | `runtime analysis` | Retrieves the list of runtime errors that have occurred in the active Dart or Flutter application. |
| `take_screenshot` | `runtime analysis` | Takes a screenshot of the active Flutter application in its current state. |
| `get_widget_tree` | `runtime analysis` | Retrieves the widget tree from the active Flutter application. |
| `get_selected_widget` | `runtime analysis` | Retrieves the selected widget from the active Flutter application. |
| `hot_reload` | `runtime tool` | Performs a hot reload of the active Flutter application. |
| `connect_dart_tooling_daemon`* | `configuration` | Connects to the locally running Dart Tooling Daemon. |
| `get_active_location` | `editor` | Gets the active cursor position in the connected editor (if available). |
| `run_tests` | `static tool` | Runs tests for the given project roots. |
| `create_project` | `static tool` | Creates a new Dart or Flutter project. |

> *Experimental: may be removed.
| `connect_dart_tooling_daemon` | Connect to DTD | Connects to the Dart Tooling Daemon. You should get the uri either from available tools or the user, do not just make up a random URI to pass. When asking the user for the uri, you should suggest the "Copy DTD Uri to clipboard" action. When reconnecting after losing a connection, always request a new uri first. |
| `get_runtime_errors` | Get runtime errors | Retrieves the most recent runtime errors that have occurred in the active Dart or Flutter application. Requires "connect_dart_tooling_daemon" to be successfully called first. |
| `take_screenshot` | Take screenshot | Takes a screenshot of the active Flutter application in its current state. Requires "connect_dart_tooling_daemon" to be successfully called first. |
| `hot_reload` | Hot reload | Performs a hot reload of the active Flutter application. This is to apply the latest code changes to the running application. Requires "connect_dart_tooling_daemon" to be successfully called first. |
| `get_widget_tree` | Get widget tree | Retrieves the widget tree from the active Flutter application. Requires "connect_dart_tooling_daemon" to be successfully called first. |
| `get_selected_widget` | Get selected widget | Retrieves the selected widget from the active Flutter application. Requires "connect_dart_tooling_daemon" to be successfully called first. |
| `set_widget_selection_mode` | Set Widget Selection Mode | Enables or disables widget selection mode in the active Flutter application. Requires "connect_dart_tooling_daemon" to be successfully called first. |
| `get_active_location` | Get Active Editor Location | Retrieves the current active location (e.g., cursor position) in the connected editor. Requires "connect_dart_tooling_daemon" to be successfully called first. |
| `pub_dev_search` | pub.dev search | Searches pub.dev for packages relevant to a given search query. The response will describe each result with its download count, package description, topics, license, and publisher. |
| `remove_roots` | Remove roots | Removes one or more project roots previously added via the add_roots tool. |
| `add_roots` | Add roots | Adds one or more project roots. Tools are only allowed to run under these roots, so you must call this function before passing any roots to any other tools. |
| `dart_fix` | Dart fix | Runs `dart fix --apply` for the given project roots. |
| `dart_format` | Dart format | Runs `dart format .` for the given project roots. |
| `run_tests` | Run tests | Run Dart or Flutter tests with an agent centric UX. ALWAYS use instead of `dart test` or `flutter test` shell commands. |
| `create_project` | Create project | Creates a new Dart or Flutter project. |
| `pub` | pub | Runs a pub command for the given project roots, like `dart pub get` or `flutter pub add`. |
| `analyze_files` | Analyze projects | Analyzes the entire project for errors. |
| `resolve_workspace_symbol` | Project search | Look up a symbol or symbols in all workspaces by name. Can be used to validate that a symbol exists or discover small spelling mistakes, since the search is fuzzy. |
| `signature_help` | Signature help | Get signature help for an API being used at a given cursor position in a file. |
| `hover` | Hover information | Get hover information at a given cursor position in a file. This can include documentation, type information, etc for the text at that position. |

<!-- generated -->
70 changes: 70 additions & 0 deletions pkgs/dart_mcp_server/tool/update_readme.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:io';

import 'package:dart_mcp/client.dart';

void main(List<String> args) async {
print('Getting registered tools...');

final tools = await _retrieveRegisteredTools();

final buf = StringBuffer('''
| Tool Name | Title | Description |
| --- | --- | --- |
''');
for (final tool in tools) {
buf.writeln(
'| `${tool.name}` | ${tool.displayName} | ${tool.description} |',
);
}

final readmeFile = File('README.md');
final updated = _insertBetween(
readmeFile.readAsStringSync(),
buf.toString(),
'<!-- generated -->',
);
readmeFile.writeAsStringSync(updated);

print('Wrote update tool list to ${readmeFile.path}.');
}

String _insertBetween(String original, String insertion, String marker) {
final startIndex = original.indexOf(marker) + marker.length;
final endIndex = original.lastIndexOf(marker);

return '${original.substring(0, startIndex)}\n\n'
'$insertion\n${original.substring(endIndex)}';
}

Future<List<Tool>> _retrieveRegisteredTools() async {
final client = MCPClient(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fwiw, the tools registered can vary based on the client features that are supported.

Probably, this client should claim to support all features so that all the tools show up.

Implementation(name: 'list tools client', version: '1.0.0'),
);
final process = await Process.start('dart', ['run', 'bin/main.dart']);
final server = client.connectStdioServer(
process.stdin,
process.stdout,
onDone: process.kill,
);

await server.initialize(
InitializeRequest(
protocolVersion: ProtocolVersion.latestSupported,
capabilities: client.capabilities,
clientInfo: client.implementation,
),
);
server.notifyInitialized(InitializedNotification());

final toolsResult = await server.listTools(ListToolsRequest());
await client.shutdown();
return toolsResult.tools;
}

extension on Tool {
String get displayName => toolAnnotations?.title ?? '';
}