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 2 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 @@ -55,3 +55,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.

- run: dart tool/update_readme.dart
# If this fails, you need to run 'dart tool/update_readme.dart'.
- run: git diff --exit-code
59 changes: 38 additions & 21 deletions pkgs/dart_mcp_server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,44 @@ WIP. This package is still experimental and is likely to evolve quickly.

## Tools

| Tool Name | Feature Group | 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.
<!-- run 'dart tool/update_readme.dart' to update -->

<!-- generated -->

### project

- `dart_fix`: Runs `dart fix --apply` for the given project roots.
- `dart_format`: Runs `dart format .` for the given project roots.
- `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`: Creates a new Dart or Flutter project.

### analysis

- `analyze_files`: Analyzes the entire project for errors.
- `resolve_workspace_symbol`: 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`: Get signature help for an API being used at a given cursor position in a file.
- `hover`: Get hover information at a given cursor position in a file. This can include documentation, type information, etc for the text at that position.

### runtime

- `connect_dart_tooling_daemon`: 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`: 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`: Takes a screenshot of the active Flutter application in its current state. Requires "connect_dart_tooling_daemon" to be successfully called first.
- `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`: Retrieves the widget tree from the active Flutter application. Requires "connect_dart_tooling_daemon" to be successfully called first.
- `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`: Enables or disables widget selection mode in the active Flutter application. Requires "connect_dart_tooling_daemon" to be successfully called first.
- `get_active_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

- `pub`: Runs a pub command for the given project roots, like `dart pub get` or `flutter pub add`.

### pub.dev

- `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.

<!-- generated -->

## Usage

Expand Down
7 changes: 7 additions & 0 deletions pkgs/dart_mcp_server/lib/src/mixins/analyzer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,13 @@ base mixin DartAnalyzerSupport
}());
}

static final List<Tool> allTools = [
analyzeFilesTool,
resolveWorkspaceSymbolTool,
signatureHelpTool,
hoverTool,
];

@visibleForTesting
static final analyzeFilesTool = Tool(
name: 'analyze_files',
Expand Down
7 changes: 7 additions & 0 deletions pkgs/dart_mcp_server/lib/src/mixins/dash_cli.dart
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,13 @@ base mixin DashCliSupport on ToolsSupport, LoggingSupport, RootsTrackingSupport
);
}

static final List<Tool> allTools = [
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: consider looping through this list in the initialize method so that it is less likely a new tool is added to initialize and not added here. You'd have to store that tools with their associated callback here.

dartFixTool,
dartFormatTool,
runTestsTool,
createProjectTool,
];

static final dartFixTool = Tool(
name: 'dart_fix',
description: 'Runs `dart fix --apply` for the given project roots.',
Expand Down
11 changes: 11 additions & 0 deletions pkgs/dart_mcp_server/lib/src/mixins/dtd.dart
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,17 @@ base mixin DartToolingDaemonSupport
);
}

static final List<Tool> allTools = [
connectTool,
getRuntimeErrorsTool,
screenshotTool,
hotReloadTool,
getWidgetTreeTool,
getSelectedWidgetTool,
setWidgetSelectionModeTool,
getActiveLocationTool,
];

@visibleForTesting
static final connectTool = Tool(
name: 'connect_dart_tooling_daemon',
Expand Down
2 changes: 2 additions & 0 deletions pkgs/dart_mcp_server/lib/src/mixins/pub.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ base mixin PubSupport on ToolsSupport, LoggingSupport, RootsTrackingSupport
);
}

static final List<Tool> allTools = [pubTool];

static final pubTool = Tool(
name: 'pub',
description:
Expand Down
2 changes: 2 additions & 0 deletions pkgs/dart_mcp_server/lib/src/mixins/pub_dev_search.dart
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@ base mixin PubDevSupport on ToolsSupport {
}
}

static final List<Tool> allTools = [pubDevTool];

static final pubDevTool = Tool(
name: 'pub_dev_search',
description:
Expand Down
54 changes: 54 additions & 0 deletions pkgs/dart_mcp_server/tool/update_readme.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// 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/server.dart';
import 'package:dart_mcp_server/src/mixins/analyzer.dart';
import 'package:dart_mcp_server/src/mixins/dash_cli.dart';
import 'package:dart_mcp_server/src/mixins/dtd.dart';
import 'package:dart_mcp_server/src/mixins/pub.dart';
import 'package:dart_mcp_server/src/mixins/pub_dev_search.dart';

final Map<String, List<Tool>> toolCategories = {
'project': DashCliSupport.allTools,
'analysis': DartAnalyzerSupport.allTools,
'runtime': DartToolingDaemonSupport.allTools,
'pub': PubSupport.allTools,
'pub.dev': PubDevSupport.allTools,
};

void main(List<String> args) {
final buf = StringBuffer();

for (final entry in toolCategories.entries) {
final category = entry.key;
final tools = entry.value;

buf.writeln('### $category');
buf.writeln('');
Comment on lines +29 to +30
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: use cascades


for (final tool in tools) {
buf.writeln('- `${tool.name}`: ${tool.description}');
}

buf.writeln('');
}

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

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${original.substring(endIndex)}';
}