Leveraging Gemini CLI and the underlying Gemini LLM to build Model Context Protocol (MCP) AI applications using Flutter/Dart with a local development environment.
Why not just use Python?
Python has traditionally been the main coding language for ML and AI tools. One of the strengths of the MCP protocol is that the actual implementation details are independent of the development language. The reality is that not every project is coded in Python- and MCP allows you to use the latest AI approaches with other coding languages.
Flutter/Dart? For AI? Does that even work?
The goal of this article is to provide a minimal viable basic working MCP stdio server in Dart that can be run locally without any unneeded extra code or extensions.
The key MCP Dart package is here:
What Is Flutter / Dart?
Flutter is Google’s open-source UI toolkit and framework used for building natively compiled, multi-platform applications (mobile, web, desktop, and embedded systems) from a single codebase. Dart is the programming language , also developed by Google, in which Flutter apps are written.
The full details of the language can be found here:
Installing Dart
Step by Step instructions vary by platform — a good starting point is here:
For a Debian style Linux Distro these steps are similar to:
sudo apt-get update -y && sudo apt-get upgrade -y
sudo apt-get install -y curl git unzip xz-utils zip libglu1-mesa
The download and extract the latest Flutter Bundle and extract to a common directory like ~/develop :
tar -xf <sdk_zip_path> -C <destination_directory_path>
As of writing the current version is:
tar -xf /mnt/chromeos/MyFiles/Downloads/flutter_linux_3.38.5-stable.tar.xz -C ~/develop/
You can validate the working tools with the — version command:
xbill@penguin:~$ dart --version
Dart SDK version: 3.10.4 (stable) (Tue Dec 9 00:01:55 2025 -0800) on "linux_x64"
xbill@penguin:~$ flutter --version
Flutter 3.38.5 • channel stable • https://github.com/flutter/flutter.git
Framework • revision f6ff1529fd (3 weeks ago) • 2025-12-11 11:50:07 -0500
Engine • hash c108a94d7a8273e112339e6c6833daa06e723a54 (revision 1527ae0ec5) (23 days ago) • 2025-12-11 15:04:31.000Z
Tools • Dart 3.10.4 • DevTools 2.51.1
What is FireStore?
Google FireStore, also known as Cloud FireStore is a part of the Google Firebase application development platform. It is fundamentally a cloud-hosted NoSQL database for storing and syncing data. Firestore can be directly accessed by mobile and web applications through native SDKs.
Gemini CLI
If not pre-installed you can download the Gemini CLI to interact with the source files and provide real-time assistance:
npm install -g @google/gemini-cli
Testing the Gemini CLI Environment
Once you have all the tools and the correct Node.js version in place- you can test the startup of Gemini CLI. You will need to authenticate with a Key or your Google Account:
gemini
Dart Gemini CLI Extension
To simplify working with Dart/Flutter with Gemini CLI- a Gemini CLI extension is available:
Flutter extension for Gemini CLI
The installation will look similar to this:
xbill@penguin:~/gemini-cli-codeassist/mcp-stdio-flutter$ gemini extensions install https://github.com/gemini-cli-extensions/flutter.git --auto-update
Installing extension "flutter".
**The extension you are about to install may have been created by a third-party developer and sourced from a public repository. Google does not vet, endorse, or guarantee the functionality or security of extensions. Please carefully inspect any extension and its source code before installing to understand the permissions it requires and the actions it may perform.**
This extension will run the following MCP servers:
* dart (local): dart mcp-server
This extension will append info to your gemini.md context using flutter.md
Do you want to continue? [Y/n]:
Extension "flutter" installed successfully and enabled.
xbill@penguin:~/gemini-cli-codeassist/mcp-stdio-flutter$
Node Version Management
Gemini CLI needs a consistent, up to date version of Node. The nvm command can be used to get a standard Node environment:
Where do I start?
The strategy for starting MCP development is a incremental step by step approach.
First, the basic development environment is setup with the required system variables, and a working Gemini CLI configuration.
Then, a minimal Hello World Style Dart MCP Server is built with stdio transport. This server is validated with Gemini CLI in the local environment.
The MCP server is backed by a FireStore database that provides basic product inventory.
This setup validates the connection from Gemini CLI to the local process via MCP. The MCP client (Gemini CLI) and the Dart MCP server both run in the same local environment.
Next- the basic MCP server is extended with Gemini CLI to add several new tools in standard Dart code.
Setup the Basic Environment
At this point you should have a working Dart/Flutter environment and a working Gemini CLI installation. The next step is to clone the GitHub samples repository with support scripts:
cd ~
git clone https://github.com/xbill9/gemini-cli-codeassist
Then run init.sh from the cloned directory.
The script will attempt to determine your shell environment and set the correct variables:
cd gemini-cli-codeassist
source init.sh
If your session times out or you need to re-authenticate- you can run the set_env.sh script to reset your environment variables:
cd gemini-cli-codeassist
source set_env.sh
Variables like PROJECT_ID need to be setup for use in the various build scripts- so the set_env script can be used to reset the environment if you time-out.
Hello World with STDIO Transport
One of the key features that the standard MCP libraries provide is abstracting various transport methods.
The high level MCP tool implementation is the same no matter what low level transport channel/method that the MCP Client uses to connect to a MCP Server.
The simplest transport that the SDK supports is the stdio (stdio/stdout) transport — which connects a locally running process. Both the MCP client and MCP Server must be running in the same environment.
The connection over stdio will look similar to this:
final transport = StdioServerTransport();
await server.connect(transport);
Running the Dart Code
First- switch the directory with the Dart MCP sample code:
cd ~/gemini-cli-codeassist/firestore-stdio-flutter
Current Version of Dart dependencies:
The current version of pubspec.yaml describes the project:
name: firestore_stdio_flutter
description: A Dart-based Model Context Protocol (MCP) server implementation using stdio with Firebase.
version: 1.0.1
repository: https://github.com/xbill9/gemini-cli-codeassist/firebase_stdio_flutter
environment:
sdk: ^3.10.4
# Add regular dependencies here.
dependencies:
path: ^1.9.0
mcp_dart: ^1.2.0
firedart: ^0.9.8
dotenv: ^4.2.0
dev_dependencies:
lints: ^6.0.0
test: ^1.25.6
Installing and Running the Dart Code
Run the build make target on the local system:
xbill@penguin:~/gemini-cli-codeassist/firestore-stdio-flutter$ make build
dart pub get && dart compile exe bin/firestore_stdio_flutter.dart -o bin/firestore_stdio_flutter
Resolving dependencies...
Downloading packages...
archive 3.6.1 (4.0.7 available)
googleapis_auth 1.6.0 (2.0.0 available)
grpc 3.2.4 (5.1.0 available)
protobuf 3.1.0 (6.0.0 available)
Got dependencies!
4 packages have newer versions incompatible with dependency constraints.
Try `dart pub outdated` for more information.
Generated: /home/xbill/gemini-cli-codeassist/firestore-stdio-flutter/bin/firestore_stdio_flutter
To test the Dart Code:
xbill@penguin:~/gemini-cli-codeassist/firestore-stdio-flutter$ make test
dart test
00:00 +2: All tests passed!
To lint the Dart Code:
xbill@penguin:~/gemini-cli-codeassist/firestore-stdio-flutter$ make lint
dart analyze
Analyzing firestore-stdio-flutter... 0.2s
No issues found!
Gemini CLI settings.json
The default Gemini CLI settings.json has an entry for the source:
{
"mcpServers": {
"firestore-stdio-flutter": {
"command": "/home/xbill/gemini-cli-codeassist/firestore-stdio-flutter/bin/firestore_stdio_flutter",
"args": []
}
}
}
Validation with Gemini CLI
Finally- Gemini CLI is restarted and the MCP connection over stdio to the Dart Code is validated, The full Gemini CLI Session will start:
gemini
> /mcp list
Configured MCP servers:
🟢 firestore-stdio-flutter - Ready (6 tools)
Tools:
- check_db
- get_product_by_id
- get_products
- get_root
- reset
- seed
> check_db
✦ I will check if the inventory database is running.
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ check_db (firestore-stdio-flutter MCP Server) {} │
│ │
│ Database running: true │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ The database is running. What would you like to do next?
> reset
✦ I will clear all products from the inventory database.
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ reset (firestore-stdio-flutter MCP Server) {} │
│ │
│ Database reset successfully. │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ The database has been reset successfully.
> seed
✦ I will seed the inventory database with products.
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ seed (firestore-stdio-flutter MCP Server) {} │
│ │
│ Database seeded successfully. │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ The database has been seeded successfully.
> get_products
✦ I will retrieve the list of all products from the inventory database.
✦ I have retrieved the list of products. There are several items available, including Sunflower Seeds, Wasabi Party Mix, and
White Chocolate Caramel Corn. Would you like to see more details on any specific product?
│
> Coffee
✦ I will retrieve the details for the Coffee Beans product.
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ get_product_by_id (firestore-stdio-flutter MCP Server) {"id":"tJ7Br576FxaCoB6Iye55"} │
│ │
│ {"id":"tJ7Br576FxaCoB6Iye55","name":"Coffee │
│ Beans","price":6.0,"quantity":73,"imgfile":"product-images/coffeebeans.png","timestamp":"2025-02-05T07:43:28.742323","actuald │
│ ateadded":"2026-01-06T12:43:45.268326"} │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ The Coffee Beans are priced at $6.00, and there are 73 units currently in stock. Would you like to know anything else about
this product?
Using the Dart Gemini CLI Extension
The Gemini CLI Extension provides tools for working with Dart Code:
> run_tests
✦ I will run the project's tests to ensure everything is functioning correctly.
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ? run_tests (dart MCP Server) {"roots":[{"root":"file:///home/xbill/gemini-cli-codeassist/firestore-stdio-flutter"}]} ← │
│ │
│ MCP Server: dart │
│ Tool: run_tests │
│ │
│ Allow execution of MCP tool "run_tests" from server "dart"? │
│ │
│ 1. Allow once │
│ 2. Allow tool for this session │
│ ● 3. Allow all server tools for this session │
│ 4. No, suggest changes (esc) │
│ │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ run_tests (dart MCP Server) {"roots":[{"root":"file:///home/xbill/gemini-cli-codeassist/firestore-stdio-flutter"}]} │
│ │
│ dart|flutter test in /home/xbill/gemini-cli-codeassist/firestore-stdio-flutter: │
│ \u001b[32m+2\u001b[0m: All tests passed!\u001b[0m │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ Tests passed successfully. I'm ready for your next instruction.
> dart_fix
✦ I will run dart fix --apply to automatically address common issues and keep the codebase clean.
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ dart_fix (dart MCP Server) {"roots":[{"root":"file:///home/xbill/gemini-cli-codeassist/firestore-stdio-flutter"}]} │
│ │
│ dart fix in /home/xbill/gemini-cli-codeassist/firestore-stdio-flutter: │
│ Computing fixes in firestore-stdio-flutter... │
│ Nothing to fix! │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ dart fix found nothing to change. How can I help you next?
> dart_foramt
✦ I will run dart format . to ensure the code follows standard Dart formatting conventions.
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ dart_format (dart MCP Server) {"roots":[{"paths":["."],"root":"file:///home/xbill/gemini-cli-codeassist/firestore-stdio-f… │
│ │
│ dart format in /home/xbill/gemini-cli-codeassist/firestore-stdio-flutter: │
│ Formatted 4 files (0 changed) in 0.01 seconds. │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ dart format completed, and no files needed changes. What's next?
Publishing Dart Packages with Gemini CLI
Gemini CLI offers support and automation for publishing your Dart code. Start the processs from within Gemini CLI:
✦ The package is ready for publishing with 0 warnings. I will now run dart pub publish. Please note that this command may require
you to authenticate via a web browser or provide input in the terminal (press ctrl + f to focus the shell if needed).
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ Shell dart pub publish [current working directory /home/xbill/gemini-cli-codeassist/firestore-stdio-flutter] (Publishing … │
│ │
│ Resolving dependencies... │
│ Downloading packages... │
│ archive 3.6.1 (4.0.7 available) │
│ googleapis_auth 1.6.0 (2.0.0 available) │
│ grpc 3.2.4 (5.1.0 available) │
│ protobuf 3.1.0 (6.0.0 available) │
│ Got dependencies! │
│ 4 packages have newer versions incompatible with dependency constraints. │
│ Try `dart pub outdated` for more information. │
│ Publishing firestore_stdio_flutter 1.0.1 to https://pub.dev: │
│ ├── CHANGELOG.md (<1 KB) │
│ ├── GEMINI.md (1 KB) │
│ ├── LICENSE (1 KB) │
│ ├── Makefile (<1 KB) │
│ ├── README.md (1 KB) │
│ ├── analysis_options.yaml (1 KB) │
│ ├── bin │
│ │ └── firestore_stdio_flutter.dart (2 KB) │
│ ├── lib │
│ │ ├── product.dart (1 KB) │
│ │ └── tools.dart (7 KB) │
│ ├── pubspec.yaml (<1 KB) │
│ └── test │
│ └── greet_test.dart (<1 KB) │
│ │
│ Total compressed archive size: 6 KB. │
│ Validating package... │
│ │
│ Publishing is forever; packages cannot be unpublished. │
│ Policy details are available at https://pub.dev/policy │
│ │
│ Do you want to publish firestore_stdio_flutter 1.0.1 to https://pub.dev (y/N)? y │
│ Uploading... (1.6s) │
│ Message from server: Successfully uploaded https://pub.dev/packages/firestore_stdio_flutter version 1.0.1, it may take up-to │
│ 10 minutes before the new version is available. │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ The package firestore_stdio_flutter 1.0.1 has been successfully published to pub.dev. It may take up to 10 minutes for the new
version to appear on the site.
Extending the Dart MCP Server with Gemini CLI
Now that the basic MCP functionality has been tested and verified with Gemini CLI- the Dart code can be extended with new MCP tools:
> extend @bin/firebase_stdio_flutter.dart with new MCP tools -
one that builds a detailled inventory report and
one that gets dart and flutter runtime information
Gemini CLI will get right to work:
281 + │
│ 282 + Future<CallToolResult> getInventoryReportHandler( │
│ 283 + Map<String, dynamic> args, │
│ 284 + dynamic extra, │
│ 285 + ) async { │
│ 286 + if (!dbRunning) { │
│ 287 + return CallToolResult( │
│ 288 + isError: true, │
│ 289 + content: [TextContent(text: "Inventory database is not running.")], │
│ 290 + ); │
│ 291 + } │
│ 292 + try { │
│ 293 + final productsSnapshot = │
│ 294 + await Firestore.instance.collection("inventory").get(); │
│ 295 + final products = │
│ 296 + productsSnapshot.map((doc) => Product.fromFirestore(doc)).toList(); │
Once the tools are generated you will get a confirmation:
✦ I have successfully extended the firestore-stdio-flutter application with the requested MCP tools.
Here's a summary of the changes:
1. Modified `lib/tools.dart`: Added two new handler functions:
* getInventoryReportHandler: Fetches all products, calculates total quantity, total value, identifies the most expensive
item, and lists items with low stock (quantity < 10). It returns a formatted text report.
* getRuntimeInfoHandler: Retrieves the current Dart version using Platform.version and attempts to get the Flutter version
by running flutter --version.
2. Modified `bin/firestore_stdio_flutter.dart`: Registered the new tools (get_inventory_report and get_runtime_info) with the
MCP server so they can be called by clients.
3. Created `test/inventory_tools_test.dart`: Added a test file to verify the get_runtime_info tool and the error handling of
get_inventory_report (when the database is not running).
Verified the changes by running the tests and dart analyze.
User, please restart the server to use the new tools.
Restart Gemini CLI and check for the new MCP tools:
xbill@penguin:~/gemini-cli-codeassist/firestore-stdio-flutter$ make build
dart pub get && dart compile exe bin/firestore_stdio_flutter.dart -o bin/firestore_stdio_flutter
Resolving dependencies...
Downloading packages...
Generated: /home/xbill/gemini-cli-codeassist/firestore-stdio-flutter/bin/firestore_stdio_flutter
gemini
> /mcp list
Configured MCP servers:
🟢 firestore-stdio-flutter - Ready (8 tools)
Tools:
- check_db
- get_inventory_report
- get_product_by_id
- get_products
- get_root
- get_runtime_info
- reset
- seed
The new MCP tools can be used in the current context:
> get_runtime_info
✦ I will retrieve the Dart and Flutter runtime information for you.
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ get_runtime_info (firestore-stdio-flutter MCP Server) {} │
│ │
│ === Runtime Information === │
│ Dart Version: 3.10.4 (stable) (Tue Dec 9 00:01:55 2025 -0800) on "linux_x64" │
│ OS: linux Linux 6.6.99-09000-gd3ae1caecf39 #1 SMP PREEMPT_DYNAMIC Thu, 27 Nov 2025 21:00:42 -0800 │
│ Flutter Version: Flutter 3.38.5 • channel stable • https://github.com/flutter/flutter.git │
│ Framework • revision f6ff1529fd (4 weeks ago) • 2025-12-11 11:50:07 -0500 │
│ Engine • hash c108a94d7a8273e112339e6c6833daa06e723a54 (revision 1527ae0ec5) (26 days ago) • 2025-12-11 15:04:31.000Z │
│ Tools • Dart 3.10.4 • DevTools 2.51.1 │
│ =========================== │
│ │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ The runtime information has been retrieved:
* Dart Version: 3.10.4 (stable)
* Flutter Version: 3.38.5 (stable)
* OS: Linux 6.6.99
I am ready for your next command.
and inventory information:
> get_inventory_report
✦ I will now generate a detailed inventory report for you, including total value and low stock items.
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ get_inventory_report (firestore-stdio-flutter MCP Server) {} │
│ │
│ === Inventory Report === │
│ Total Products: 34 │
│ Total Quantity: 6699 │
│ Total Value: $41331.00 │
│ Most Expensive Item: Sunflower Seeds ($10.00) │
│ Low Stock Items (< 10): │
│ - Wasabi Party Mix (Qty: 0) │
│ - Jalapeno Seasoning (Qty: 0) │
│ ======================== │
│ │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ The inventory report has been generated:
* Total Products: 34
* Total Quantity: 6,699
* Total Value: $41,331.00
* Most Expensive Item: Sunflower Seeds ($10.00)
* Low Stock Items:
* Wasabi Party Mix (Qty: 0)
* Jalapeno Seasoning (Qty: 0)
Use The New MCP Tools in the Current Context
Once the generated code has been exposed as MCP tools - the current context in Gemini CLI has full access to the information:
> with get_inventory_report and current products recommend
a menu that optimizes profit
✦ Based on the inventory report and current product list, here is a recommended menu designed to optimize profit.
Strategy: This menu prioritizes High-Value Items ($8 - $10) that are currently in stock. By featuring premium-priced goods, we
aim to maximize revenue per transaction. Items with 0 quantity (Wasabi Party Mix, Jalapeno Seasoning) have been excluded.
💰 High-Yield Menu Recommendations
Starters & Snacks
Focusing on high-ticket pantry items.
* Sunflower Seeds - $10.00 (High Stock: 361)
* Parmesan Crisps - $9.00
* Walnuts - $8.00
Mains
Premium protein and staples.
* Shrimp Feast - $10.00
* Whole Chicken - $6.00 (Volume driver: 250 in stock)
* Side of Black Beans - $8.00
Beverages
Top-tier drink selection.
* Premium Green Tea - $10.00 (High Stock: 424)
* Classic Cola - $9.00
* Apple Juice - $8.00
Sweets & Spreads
High-margin dessert add-ons.
* Mint Chocolate Cookies - $10.00
* Maple Almond Butter - $10.00
* Fresh Bananas - $9.00
---
💡 Inventory Note: You currently have 0 stock of Wasabi Party Mix and Jalapeno Seasoning. Ensure these are removed from any
active physical menus to avoid customer dissatisfaction.
The information from the MCP tool execution comes back into the current Gemini CLI context. You can use the information returned from the tools along with the underlying Gemini Models.
Summary
The strategy for using Dart/Flutter for MCP development with Gemini CLI was validated with a incremental step by step approach.
A minimal stdio transport MCP Server was started from source code and validated with Gemini CLI running as a MCP client in the same local environment.
FireStore was used as a backing database to provide basic inventory support.
Gemini CLI was then used to extend the sample source code with several new MCP tools and use these tools inside the context for the underlying LLM.
This approach can be extended to more complex deployments using other MCP transports and Cloud based options.


Top comments (0)