1 of 52

Dart beyond Flutter, building AI tools for modern AI Apps

2 of 52

Nagpur

Aditya Thakur

Aditya's goal is to empower and inspire developers and learners to create impactful and innovative solutions using technology.

​

Google Developer Expert Flutter and Dart

Software Engineer Scapia (scapia.cards)

Content Creator YouTube (13K)��Contributor to Flutter (featured in Notable Commits), FlutterFire and Flutter Community Plus Plugins.

3 of 52

Do I write code at work?

"Not as much as I hope to."

AI SHIFT

Augmented Workflows

My work over the last year has shifted. We have been actively using AI at work. Whether it is daily emails that go out or to make sense of data or to ideate and create new features.

SDD

SPEC Driven

We follow SPEC Driven Development (SDD) and have workflows built around it. It starts all the way at discovery, going through gathering requirements, HLD, LLD and then tasks which it implements.

4 of 52

SPEC Driven Development

The structured lifecycle of SDD

01

Discovery

Initial phase exploring concepts.

02

Requirements

Gathering functional specs.

03

HLD

High-Level system architecture.

04

LLD

Low-Level software blueprints.

05

Tasks

Actionable items created.

DEPLOY

Execution

Implementing tasks in code.

5 of 52

What is Flutter?

The modern framework for multi-platform client applications

Production-Grade Framework

Build high-quality, rich, and beautiful experiences across a multitude of device classes from a single shared source codebase.

• iOS & Android • Web & Desktop • Embedded

Developer Productivity

Shifts your focus from platform compatibility to pure creation. Write once, compile to native code, and iterate instantly with hot reload.

⚡ Dart is the Language behind Flutter

Since you are learning Dart for server-side development, you already know the language needed to build beautiful, high-performance mobile and web apps with Flutter! Code reuse extends from your backend server straight to your clients.

6 of 52

iOS

Android

Web

Windows

Mac OS

Linux

Embedded

(early stage)

Production-grade apps from a single code base

These trademarks are the property of their respective owners and that �Google is not endorsed by or affiliated with the respective third party companies.

7 of 52

Do you work with Dart?

business_center

Production Use

We use Dart heavily at work for sending statement emails over Node.js and Python, and for sharing merchandising data.

code

Shared Ecosystem

With internal dashboards built on Flutter Web, using Dart on the server enables seamless code reuse of our shared utilities.

speed

High Performance

In the DeltaBlue benchmark, Dart's JIT runtime matches or outperforms JavaScript/V8, and even optimized C in long-running workloads.

8 of 52

9 of 52

10 of 52

11 of 52

What is Model Context Protocol (MCP)?

Model Context Protocol (MCP), a new standard for connecting AI assistants to the systems where data lives, including content repositories, business tools, and development environments.

  • MCP is an open protocol that standardizes how applications provide context to LLMs.
  • Think of MCP like a USB-C port for AI applications.
  • MCP provides a standardized way to connect AI models to different data sources and tools.

12 of 52

13 of 52

Specification

  • Hosts: LLM applications that initiate connections
  • Clients: Connectors within the host application
  • Servers: Services that provide context and capabilities

​

The protocol uses JSON-RPC 2.0 messages to establish communication between them.

14 of 52

15 of 52

16 of 52

1. Communication & Social

- WhatsApp: Message analysis and automation

- Slack: Get Claude analyzing your conversations

- Discord: Community engagement and moderation

​

2. Search & Discovery

- Brave Search: Real-time web information

- Airbnb: Accommodation search

​

3. Business & E-commerce

- Shopify: E-commerce platform management

- Asana: Project management

- HubSpot: Marketing, sales, and service

​

4. Development & Creative Tools

- GitHub: Code analysis and repo management

- VS Code: Code editing and IDE integration

- Blender: 3D modeling and animation

- Figma: Design collaboration and prototyping

​

5. Knowledge & Workspace

- Notion: Workspaces management

- Google Drive: Document storage

- Airtable: Structured database management

​

6. Data & Storage

- PostgreSQL: Enterprise-grade relational database

- MySQL: Popular open-source database

- SQLite: Lightweight file-based database

github.com/modelcontextprotocol/servers

github.com/punkpeye/awesome-mcp-servers

17 of 52

1. Communication & Social

- WhatsApp: Message analysis and automation

- Slack: Get Claude analyzing your conversations

- Discord: Community engagement and moderation

​

2. Search & Discovery

- Brave Search: Real-time web information

- Airbnb: Accommodation search

​

3. Business & E-commerce

- Shopify: E-commerce platform management

- Asana: Project management

- HubSpot: Marketing, sales, and service

​

4. Development & Creative Tools

- GitHub: Code analysis and repo management

- VS Code: Code editing and IDE integration

- Blender: 3D modeling and animation

- Figma: Design collaboration and prototyping

​

5. Knowledge & Workspace

- Notion: Workspaces management

- Google Drive: Document storage

- Airtable: Structured database management

​

6. Data & Storage

- PostgreSQL: Enterprise-grade relational database

- MySQL: Popular open-source database

- SQLite: Lightweight file-based database

github.com/modelcontextprotocol/servers

github.com/punkpeye/awesome-mcp-servers

18 of 52

19 of 52

How to build using Dart?

Community

Packages

20 of 52

How to build using Dart?

Jhin Lee (@leehack on GitHub)

sharing about Flutter to communicate with the Playwright MCP server, which then drives Playwright for browser automation.

21 of 52

How to build using Dart?

22 of 52

How to build using Dart?

23 of 52

Code

24 of 52

dart create -t server-shelf mcp_server_demo

25 of 52

dart pub add dart_mcp

26 of 52

How to build using Dart?

class DartMCPServer extends MCPServer with ToolsSupport {

​

DartMCPServer({required super.channel})

: super.fromStreamChannel(

​

implementation: ServerImplementation(

name: 'aditya mcp server',

version: '0.1.0',

),

instructions:

'Finds latest information about Aditya Thakur and analytics data for his app',

);

​

//more code

​

27 of 52

How to build using Dart?

class DartMCPServer extends MCPServer with ToolsSupport {

​

DartMCPServer({required super.channel})

: super.fromStreamChannel(

​

implementation: ServerImplementation(

name: 'aditya mcp server',

version: '0.1.0',

),

instructions:

'Finds latest information about Aditya Thakur and analytics data for his app',

);

​

//more code

​

Base class to extend when implementing an MCP server.

28 of 52

How to build using Dart?

class DartMCPServer extends MCPServer with ToolsSupport {

​

DartMCPServer({required super.channel})

: super.fromStreamChannel(

​

implementation: ServerImplementation(

name: 'aditya mcp server',

version: '0.1.0',

),

instructions:

'Finds latest information about Aditya Thakur and analytics data for his app',

);

​

//more code

​

Base class to extend when implementing an MCP server.

A mixin for MCP servers which support the tools capability.

Actual functionality beyond server initialization is done by mixing in additional support mixins such as [ToolsSupport], [ResourcesSupport] etc.

29 of 52

How to build using Dart?

class DartMCPServer extends MCPServer with ToolsSupport {

​

DartMCPServer({required super.channel})

: super.fromStreamChannel(

​

implementation: ServerImplementation(

name: 'aditya mcp server',

version: '0.1.0',

),

instructions:

'Finds latest information about Aditya Thakur and analytics data for his app',

);

​

//more code

​

The name, current version, and other info to give to the client.

30 of 52

How to build using Dart?

class DartMCPServer extends MCPServer with ToolsSupport {

​

DartMCPServer({required super.channel})

: super.fromStreamChannel(

​

implementation: ServerImplementation(

name: 'aditya mcp server',

version: '0.1.0',

),

instructions:

'Finds latest information about Aditya Thakur and analytics data for his app',

);

​

//more code

​

31 of 52

How to create a tool?

@override

FutureOr<InitializeResult> initialize(InitializeRequest request) {

registerTool(

Tool(name: 'about_aditya', inputSchema: ObjectSchema()),

(_) => CallToolResult(

content: [

TextContent(

text: '''

I'm a Software Engineer at Scapia, …

''',

),

],

),

);

​

Servers should register tools using the [registerTool] method, typically inside the [initialize] method, but they may also be registered after initialization if needed.

​

32 of 52

How to create a tool?

@override

FutureOr<InitializeResult> initialize(InitializeRequest request) {

registerTool(

Tool(name: 'about_aditya', inputSchema: ObjectSchema()),

(_) => CallToolResult(

content: [

TextContent(

text: '''

I'm a Software Engineer at Scapia, …

''',

),

],

),

);

​

Servers should register tools using the [registerTool] method, typically inside the [initialize] method, but they may also be registered after initialization if needed.

​

33 of 52

How to accept an input?

inputSchema: ObjectSchema(

properties: {

'days': NumberSchema(

description: 'Number of days to fetch data for (default: 30)',

),

'metric': StringSchema(

description: 'Metric to fetch (default: "screenPageViews")',

),

'dimension': StringSchema(

description: 'Dimension to fetch (default: "date")',

),

},

),

​

34 of 52

How to accept an input?

inputSchema: ObjectSchema(

properties: {

'days': NumberSchema(

description: 'Number of days to fetch data for (default: 30)',

),

'metric': StringSchema(

description: 'Metric to fetch (default: "screenPageViews")',

),

'dimension': StringSchema(

description: 'Dimension to fetch (default: "date")',

),

},

),

​

35 of 52

36 of 52

37 of 52

38 of 52

39 of 52

40 of 52

41 of 52

42 of 52

43 of 52

(params) async {

try {

final days = params.arguments?['days'] as int? ?? 30;

final eventName =

params.arguments?['eventName'] as String? ?? 'button_clicked';

​

final analyticsData = await fetchEventAnalyticsData(days, eventName);

​

return CallToolResult(content: [TextContent(text: analyticsData)]);

} catch (e) {

return CallToolResult(

content: [

TextContent(

text: 'Error fetching event analytics data: ${e.toString()}',

),

],

);

}

},

44 of 52

45 of 52

Deployment

46 of 52

Problem

final server = MerchMCPServer(

stdioChannel(input: stdin, output: stdout), // ← pipes

);

Key Constraints:

  • Only works when a parent process (Claude Desktop) spawns it and talks over pipes.
  • Cannot be reached over the network.

47 of 52

Solution

What do we need to do?

1. Bind Server

HttpServer on $PORT (8080)

2. Implement MCP Spec (2025-03-26)

  • GET /health: Liveness probe
  • POST /mcp: Client → server JSON-RPC

swap_calls

Streamable HTTP

Benefits

  • Simple to implement
  • Works over standard HTTP/1.1
  • Compatible with existing infrastructure

Limitations

  • No built-in event reconnection
  • Limited to unidirectional streaming
  • Unable to handle automatic event IDs/types

rss_feed

SSE

Benefits

  • Built-in reconnection support
  • Event IDs and types support
  • Designed for server-to-client streaming
  • Lightweight over HTTP

Limitations

  • Supported mainly in modern browsers
  • Limited to text/event-stream MIME
  • No support for binary data

48 of 52

Protocol Flow: HTTP+SSE vs. Streamable HTTP

HTTP + SSE (Traditional)

Client

Client

Server

Server

1. Open SSE Connection

2. Endpoint Event

LOOP

HTTP POST Request

Respond with Message Event

3. Close Connection

VS

Streamable HTTP (MCP Spec)

Client

Client

Server

Server

1. HTTP POST Request

2. HTTP Response

LOOP

Server Opens SSE Conn

SSE Messages Sent

3. SSE Response

49 of 52

Analogy: SSE vs. Streamable HTTP

SSE = Radio Broadcast

One-way transmission: You tune in and just listen.

Streamable HTTP = Phone Call

Two-way interaction: You ask, server replies in parts.

50 of 52

phone_disabledHTTP Server as a Phone Number

Connection opens, request/response occurs, then connection closes immediately.

⚠️ Limitation: MCP needs ongoing, persistent communication.

sensorsSSE as an Open Line

Ongoing broadcast stream where server continuously pushes messages to the client.

✓ Perfect for real-time, one-way event streaming.

support_agentSession Registry as a Receptionist

devicesClients

Multiple active client requests

badgeSession Registry

Routes & assigns unique session IDs

folder_openStream Channels

Maps clients to individual stream buffers

dnsMCP Server

stdio-based stdio connection

Many clients ➔ session-managed streams ➔ one simple stdio-based MCP server

51 of 52

SUCCESSFULLY DEPLOYED

Your Dart-built MCP server is live!

It is now available on the web to connect remotely.

share

1. Share the URL

Copy your production deployment URL and share it with your team or client applications.

settings

2. Add to Config

Add the remote SSE endpoint to your local Claude Desktop or client configuration file.

bolt

3. Use It Remotely

Start querying your tools, resources, and prompts seamlessly across secure network connections!

52 of 52

Nagpur

Thank you!

Aditya Thakur

Software Engineer

mail@adityathakur.com