Architecture of Dart MCP Server

This document outlines the high-level architecture of the dart_mcp_server and its underlying core library dart_mcp.

High-Level Overview

The Dart MCP Server is an implementation of the Model Context Protocol (MCP). It acts as a bridge between an AI-assistant client (like the Antigravity CLI or an IDE plugin) and the Dart/Flutter development environment.

flowchart LR
    Client[AI Client] <-->|JSON-RPC 2.0 over stdio| Server[Dart MCP Server]

    subgraph Dart MCP Server
        Router[JSON-RPC Router]
        Tools[Tool Handlers]
        Resources[Resource Handlers]
        Prompts[Prompt Handlers]
        Router <--> Tools
        Router <--> Resources
        Router <--> Prompts
    end

    Tools --> DartCLI[Dart CLI]
    Tools --> FlutterCLI[Flutter CLI]
    Tools --> DTD[Dart Tooling Daemon]
    Tools --> Analyzer[Language Server Protocol]

Package Structure

The project is split into two primary packages:

  1. dart_mcp: The foundational library implementing the MCP specification. It provides base classes for both Clients and Servers, defining the API types, JSON-RPC communication, and standard MCP capabilities (Tools, Resources, Prompts, etc.) via mixins.
  2. dart_mcp_server: The concrete implementation of a server tailored for Dart and Flutter. It extends the base MCPServer and implements specific tools (like hotReload, analyzeFiles, launchApp) by interacting with the Dart CLI, Flutter CLI, and the Dart Tooling Daemon (DTD).

Core Class Architecture & Mixins

The server uses a heavily mixin-based architecture. This allows for clean separation of concerns, where each MCP capability and each set of tools can be developed and maintained independently.

classDiagram
    class MCPBase {
        <<abstract>>
        +registerMethod()
        +sendRequest()
        +sendNotification()
    }

    class MCPServer {
        <<abstract>>
        +initialize()
    }

    class ToolsSupport {
        <<mixin>>
        +registerTool()
        +unregisterTool()
    }

    class ResourcesSupport {
        <<mixin>>
        +addResource()
        +updateResource()
        +removeResource()
    }

    class PromptsSupport {
        <<mixin>>
        +registerPrompt()
        +unregisterPrompt()
    }

    class LoggingSupport {
        <<mixin>>
        +log()
    }

    class RootsTrackingSupport {
        <<mixin>>
        +updateRoots()
    }

    class DartMCPServer {
        +run()
    }

    class FlutterLauncherSupport {
        <<mixin>>
        +launchApp
        +stopApp
        +listDevices
        +getAppLogs
        +listRunningApps
    }

    class DartAnalyzerSupport {
        <<mixin>>
        +analyzeFiles
        +lsp
    }

    class DartToolingDaemonSupport {
        <<mixin>>
        +dtd
        +getRuntimeErrors
        +getActiveLocation
        +hotRestart
        +hotReload
        +widgetInspector
        +flutterDriver
        +callVmServiceMethod
    }

    class PubSupport {
        <<mixin>>
        +pub
    }

    class PubDevSearchSupport {
        <<mixin>>
        +pubDevSearch
    }

    class AnalyticsSupport {
        <<mixin>>
        +analytics
    }

    MCPBase <|-- MCPServer
    MCPServer <|-- DartMCPServer

    ToolsSupport <|-- DartMCPServer : with
    ResourcesSupport <|-- DartMCPServer : with
    PromptsSupport <|-- DartMCPServer : with
    LoggingSupport <|-- DartMCPServer : with
    RootsTrackingSupport <|-- DartMCPServer : with

    FlutterLauncherSupport <|-- DartMCPServer : with
    DartAnalyzerSupport <|-- DartMCPServer : with
    DartToolingDaemonSupport <|-- DartMCPServer : with
    PubSupport <|-- DartMCPServer : with
    PubDevSearchSupport <|-- DartMCPServer : with
    AnalyticsSupport <|-- DartMCPServer : with

dart_mcp Mixins

The foundational package provides mixins corresponding to MCP specification features:

  • ToolsSupport: Allows registering tools that the LLM can call.
  • ResourcesSupport: Manages exposing local data and files to the client as resources.
  • PromptsSupport: Provides a list of pre-defined prompts to the client.
  • LoggingSupport: Structured server-to-client log messages.
  • RootsTrackingSupport: Tracks the client's project roots to provide workspace context to tools.

dart_mcp_server Mixins

The concrete server composes tools by mixing in specialized feature sets:

  • FlutterLauncherSupport: App lifecycle management (launchApp, stopApp, listDevices).
  • DartAnalyzerSupport: Static analysis of Dart code (analyzeFiles).
  • DartToolingDaemonSupport: Dart Tooling Daemon integration for hot reload, hot restart, and widget tree inspection.
  • PubSupport: Package management tools.
  • PubDevSearchSupport: Querying packages from pub.dev.
  • AnalyticsSupport: Telemetry and usage tracking.

Deep Dive: Key Tooling Subsystems

Dart Tooling Daemon (DTD) Integration

The DartToolingDaemonSupport mixin is responsible for bridging the MCP server with the Dart Tooling Daemon. DTD serves as a central hub for communication between various Dart tools, IDEs, and running Dart/Flutter applications.

Auto-Discovery and Connection: When the MCP server connects to a DTD instance, it subscribes to DTD service events (like ConnectedAppServiceConstants.vmServiceRegistered) and Editor streams. This allows the MCP server to automatically discover any Dart or Flutter apps connected to that DTD instance, regardless of whether they were launched by an IDE, the CLI, or the MCP server itself. The server automatically establishes VM Service connections to these newly discovered apps and tracks them.

Supported Features:

  • App Lifecycle & Execution: Tools to trigger hotReload and hotRestart on connected applications.
  • Diagnostics: The getRuntimeErrors tool monitors the VM service error stream, capturing and providing access to recent runtime exceptions for the apps.
  • Widget Inspector: The widgetInspector tool interacts with the ext.flutter.inspector service extension to fetch the widget tree, select widgets, and change the selection mode.
  • Flutter Driver: Enables running Flutter Driver commands against connected applications for UI automation.
  • Direct VM Service access: The callVmServiceMethod tool allows making arbitrary, raw RPC calls to the VM service of a connected app.

Analyzer Integration

The DartAnalyzerSupport mixin integrates the Dart Language Server Protocol (LSP) into the MCP server. Rather than running a one-off analysis pass, it starts and manages a persistent dart language-server process.

Persistent Workspace Analysis: When the client's project workspace roots change (tracked via the RootsTrackingSupport mixin), the analyzer mixin dynamically updates the LSP workspace folders. The server remains active in the background, listening for file changes and diagnostics.

Supported Features:

  • Diagnostics & Quick Fixes: The analyzeFiles tool queries the LSP server for current workspace diagnostics. It can also request the LSP server to apply quick fixes (dart.edit.fixAllInWorkspace), which the MCP server translates into filesystem edits via workspace/applyEdit events from the language server.
  • Language Intelligence: The lsp tool exposes deep IDE-like capabilities, including:
    • hover: Provides documentation and type information for a specific position in the code.
    • signatureHelp: Returns parameter information for function calls.
    • resolveWorkspaceSymbol: Enables searching for classes, methods, and variables across the entire workspace.

Request Lifecycle

When a client wants to invoke a tool, the request flows through the base communication layer into the specific mixin that registered the tool.

sequenceDiagram
    participant AI as AI Client
    participant Base as MCPBase (JSON-RPC)
    participant Server as DartMCPServer
    participant Mixin as Tool Mixin (e.g., Dtd)
    participant Exec as External Process (e.g., DTD)

    AI->>Base: Request `tools/call` (name: "hotReload")
    Base->>Server: Route request to Tool Handler
    Server->>Mixin: Invoke registered callback
    Mixin->>Exec: Call actual service (e.g., ext.flutter.app.hotReload)
    Exec-->>Mixin: Return Result / Status
    Mixin-->>Server: Return MCP ToolResult
    Server-->>Base: Format as JSON-RPC Response
    Base-->>AI: Response

Transport Mechanism

By default, the dart_mcp_server communicates with clients over standard input/output (stdio). The lib/stdio.dart utility in dart_mcp creates a StreamChannel wrapping stdin and stdout, which the MCPBase uses for JSON-RPC 2.0 message passing. This allows the server to be seamlessly spawned as a subprocess by clients like the Antigravity CLI or IDE extensions.