Skip to content

feat(dart_mcp_server): add HTTP network inspection tools#422

Closed
ThangVuNguyenViet wants to merge 10 commits intodart-lang:mainfrom
ThangVuNguyenViet:main
Closed

feat(dart_mcp_server): add HTTP network inspection tools#422
ThangVuNguyenViet wants to merge 10 commits intodart-lang:mainfrom
ThangVuNguyenViet:main

Conversation

@ThangVuNguyenViet
Copy link
Copy Markdown

Summary

Implements the network inspection tools proposed in #269.

  • Auto-enables HTTP profiling (ext.dart.io.httpEnableTimelineLogging) on every isolate when a VM service connects, so requests are captured from app start with no app-side code changes required
  • Adds get_network_logs — fetch recorded HTTP requests, with optional updatedSince for polling
  • Adds clear_network_logs — reset the HTTP profile buffer
  • Adds get_network_request — fetch full detail (headers + body) for a single request by ID
  • New networkInspector feature category (child of dartToolingDaemon), disabled by default — opt in via --enable=networkInspector

Uses ext.dart.io.* extensions registered by the Dart runtime itself for any dart:io app in debug mode.

Closes #269 (partial — web/CDP transport not included in this PR)

Test plan

  • In-process tests pass: dart test --enable-experiment=private-named-parameters test/tools/network_inspector_test.dart --name "in-process"
  • Full integration tests pass with correct Dart dev SDK (^3.12.0-257.0.dev)
  • Manually verify with flutter run + --enable=networkInspector flag

Notes

  • dart_test.yaml with enable_experiment: [private-named-parameters] added to allow running tests locally with Dart stable SDK during development; this can be removed once the repo targets a released SDK
  • The chore: relax SDK constraint commit is for local development only and should be reverted before merge

@google-cla
Copy link
Copy Markdown

google-cla bot commented Apr 2, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

Copy link
Copy Markdown
Contributor

@jakemac53 jakemac53 left a comment

Choose a reason for hiding this comment

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

Awesome, this is a great start! 🚀 🥳

One higher level comment is that we are moving to a pattern of "meta tools" generally in order to save on tool counts (and tokens). To be consistent with that please migrate these all to a single "network" tool, with a "command" argument. See the DTD tool as an example.

description:
'Fetches recorded HTTP requests from the running app. '
'HTTP profiling is enabled automatically when the app connects, so '
'requests are captured from app start. Use updatedSince to poll only '
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: logs are not actually captured from app start, they are only captured once we connect.

I think we actually should have an explicit tool call though to start capturing logs, and also to stop capturing them. Otherwise I think we will implicitly have a bit of a memory leak here?

late TestHarness testHarness;

group('network inspector tools', () {
group('[in-process]', () {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: I would just make all these tests uses an in process test harness - we really only need a few total tests that use an out of process MCP server, and its much easier to debug when its in process

@@ -0,0 +1,698 @@
# Network Inspector Implementation Plan
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: Please remove these docs from the PR :)

@@ -0,0 +1,2 @@
enable_experiment:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: we should not be enabling experiments in any code we land here, even for tests

models.
publish_to: none
environment:
sdk: ^3.12.0-257.0.dev
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This needs to remain at the old constraint - some of our tools do rely on stuff that only exists after this dev release (listing active DTD URIs)


expect(result.isError, isNot(true));
});
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We should add another test fixture that does make network requests, so that we can test that actual network logs can be captured, cleared, etc.

.toList();
return CallToolResult(
content: [TextContent(text: jsonEncode(requests))],
structuredContent: {'requests': requests},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: I would remove the structured content here unless we need it for something. The text content can already easily just be decoded as JSON if some tooling wants to explicitly do that.

callback: (vmService) async {
try {
final vm = await vmService.getVM();
final isolateId = vm.isolates!.first.id!;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Above we enable network logging for all isolates, but here we only will return logs for the first one.

Supporting only the root isolate for now is probably fine, but we should also only enable capturing logs for the first isolate then.

We should also file a bug and add a TODO for supporting additional isolates.

callback: (vmService) async {
try {
final vm = await vmService.getVM();
final isolateId = vm.isolates!.first.id!;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same here, we should either consistently support all the isolates or only the first one.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

PR Health

Changelog Entry ✔️
Package Changed Files

Changes to files need to be accounted for in their respective changelogs.

This check can be disabled by tagging the PR with skip-changelog-check.

@kenzieschmoll
Copy link
Copy Markdown
Contributor

I'd like to see how we can share code with the Dart DevTools network inspector here rather than maintain two copies of code that is fetching network requests from the VM service.

@ThangVuNguyenViet
Copy link
Copy Markdown
Author

Hey sorry. I did not have the intention to open this PR this the first place. I was going to, after I review what Claude did and try the work myself, which I haven't. I was afraid I'm gonna make another AI slop PR so I panicky closed the PR.

But really thanks for the comments. I'll address them and reopen the PR once it's done on my end

@jakemac53
Copy link
Copy Markdown
Contributor

@ThangVuNguyenViet fwiw this PR is quite reasonable, I wouldn't call it AI slop :D, but in general yes its a good idea to review AI code prior to sending it out.

However, I wouldn't have been able to tell this was AI without the planning docs in there 🤣

@jakemac53
Copy link
Copy Markdown
Contributor

@kenzieschmoll lets discuss at the meeting today

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Network Logs tools to dart_mcp_server

3 participants