A Flutter mobile app that demonstrates the Model Context Protocol (MCP) by creating a weather chatbot that uses real AI and external APIs.
This project was created with vibe coding β a relaxed, flow-driven approach where creativity and intuition lead the way. No overthinking, just good energy and clean code.
This app implements proper MCP architecture with clean, scalable code organization:
- π― Clean Entry Point (
main.dart
): Minimal 15-line entry point - π± App Configuration (
app.dart
): Centralized app setup and theming - π€οΈ MCP Server (
bin/weather_server.dart
): Standalone server providing weather tools - π‘ MCP Client (
services/mcp_client.dart
): Flutter client with stdio transport - π§ LLM Integration (
services/llm_service.dart
): Google Gemini AI processing - π¦οΈ Weather API (
services/weather_service.dart
): OpenWeatherMap integration - π¨ Modern UI (
widgets/
): Modular, reusable components with animations
- ποΈ Clean Architecture: Separation of UI, business logic, and data
- π¦ Modular Design: Barrel exports for clean imports
- π¨ Design System: Centralized constants and theming
- β»οΈ Reusable Components: Widget-based architecture
- π Scalability: Easy to extend and maintain
- π€ Real AI Chat: Uses Google Gemini AI for natural language understanding
- π‘οΈ Live Weather Data: Fetches real weather from OpenWeatherMap API
- π‘ True MCP Implementation: Proper client-server communication using MCP protocol
- π§ Tool Calling: AI automatically determines when and how to use weather tools
- π± Modern Mobile UI: Beautiful Flutter interface with smooth animations
- π¨ Clean Architecture: Modular, scalable, and maintainable codebase
- β»οΈ Reusable Components: Widget-based design system
- π Material Design 3: Modern UI following Google's latest design principles
- π§ Easy Configuration: Centralized constants and theming
- Visit https://aistudio.google.com/app/apikey
- Sign up for a free account
- Generate an API key
- Copy the key
- Visit https://openweathermap.org/api
- Sign up for a free account
- Generate an API key
- Copy the key
For enhanced security, this project uses --dart-define-from-file
instead of .env
files. This approach prevents API keys from being exposed in APK files when the app is built.
- Copy the example configuration:
cp .env.json.example .env.json
- Edit
.env.json
with your actual API keys:
{
"OPENWEATHER_API_KEY": "your_openweather_api_key_here",
"GEMINI_API_KEY": "your_gemini_api_key_here"
}
π Security Note: The .env.json
file is git-ignored and will not be committed to version control. This approach ensures your API keys are more secure than using traditional .env
files.
This project implements secure API key management using Flutter's --dart-define-from-file
feature:
- π± APK Protection: API keys are not embedded in the compiled APK file
- π No Asset Exposure: Keys are not stored in the
assets/
folder where they can be extracted - βοΈ Compile-time Injection: Keys are injected during compilation, not at runtime
- π« Git Safety: Configuration files are properly git-ignored
- π§ Environment Separation: Easy to maintain different keys for different environments
Method | Security Level | APK Exposure | Extraction Risk |
---|---|---|---|
.env in assets |
β Exposed | ||
--dart-define-from-file |
β High | β Protected | β Low |
The project includes preconfigured launch settings in .vscode/launch.json
that automatically use the secure configuration:
- Debug, Release, and Profile configurations
- Automatic
--dart-define-from-file=.env.json
injection - No manual command-line arguments needed
flutter pub get
If you're using VS Code, the project includes launch configurations that automatically use the secure environment setup. Just press F5 or use the Debug panel.
flutter run --dart-define-from-file=.env.json
# Debug build
flutter build apk --dart-define-from-file=.env.json
# Release build
flutter build apk --release --dart-define-from-file=.env.json
- User sends message β Flutter UI
- LLM analyzes message β Gemini AI determines if weather tools needed
- Tool calling β MCP Client calls weather server via stdio transport
- Weather data fetched β MCP Server calls OpenWeatherMap API
- Response generated β LLM creates natural language response
- Display result β Flutter UI shows the conversation
User: "What's the weather in London?"
AI: I'll check the current weather in London for you...
[MCP Tool Call: get-current-weather with params: {city: "London"}]
AI: Here's the current weather information I found:
Current Weather in London, GB:
π‘οΈ Temperature: 15Β°C (feels like 13Β°C)
π€οΈ Condition: Clouds - overcast clouds
π§ Humidity: 82%
π¬οΈ Wind: 3.6 m/s
π½ Pressure: 1008 hPa
Is there anything else you'd like to know about the weather?
The app works in demo mode even without API keys:
- Without Gemini API: Uses pattern-matching for responses
- Without Weather API: Shows demo weather data
- Full MCP: Still demonstrates proper MCP client-server communication
lib/
βββ main.dart # π― Clean entry point (15 lines!)
βββ app.dart # π± App configuration
βββ config/ # βοΈ Configuration & constants
β βββ app_constants.dart # π§ Colors, dimensions, strings
β βββ app_theme.dart # π¨ Material Design theme
βββ models/ # π Data models
β βββ chat_message.dart # π¬ Chat message structure
β βββ weather_data.dart # π‘οΈ Weather data model
β βββ models.dart # π¦ Barrel exports
βββ screens/ # π± Screen widgets
β βββ chat_screen.dart # π¬ Main chat interface
βββ services/ # π§ Business logic & APIs
β βββ chat_service.dart # π€ Chat coordination
β βββ llm_service.dart # π§ AI integration
β βββ mcp_client.dart # π‘ MCP client
β βββ mcp_weather_server.dart # π€οΈ MCP server
β βββ weather_service.dart # π¦οΈ Weather API
β βββ services.dart # π¦ Barrel exports
βββ widgets/ # π§© Reusable UI components
βββ chat/ # π¬ Chat-specific widgets
β βββ animated_message_bubble.dart
β βββ animated_send_button.dart
β βββ typing_indicator.dart
βββ ui/ # π¨ General UI widgets
β βββ chat_app_bar.dart
β βββ chat_input_area.dart
β βββ chat_loading_indicator.dart
β βββ chat_messages_list.dart
β βββ weather_widget.dart
βββ widgets.dart # π¦ Barrel exports
bin/
βββ weather_server.dart # π€οΈ Standalone MCP server
docs/ # π Comprehensive documentation
βββ getting-started.md
βββ architecture.md
βββ code-structure.md
βββ api-integration.md
βββ mcp-guide.md
βββ overview.md
This implementation demonstrates:
- Proper initialization: Client-server handshake via MCP protocol
- Tool discovery: Client lists available tools from server
- Tool execution: Client calls tools with parameters, server executes and returns results
- Error handling: Proper MCP error responses and fallbacks
- Transport layer: Uses stdio transport for local communication
- Flutter: Mobile UI framework
- MCP Dart: Official Dart implementation of Model Context Protocol
- Google Gemini: Free AI inference API
- OpenWeatherMap: Free weather data API
- HTTP: For API communications
π Comprehensive documentation available in the docs/
folder:
- Getting Started Guide - Setup and installation
- Architecture Guide - How everything works together
- Code Structure Guide - Clean architecture and code organization
- API Integration Guide - Working with external APIs
- MCP Guide - Understanding Model Context Protocol
- Project Overview - High-level project explanation
- Ensure
dart run bin/weather_server.dart
works standalone - Check environment variables are properly set
- Verify API keys are correct in
.env
file - Check internet connection for API calls
- Review API quotas (both services offer generous free tiers)
- Run
flutter doctor
to check Flutter setup - Try
flutter clean && flutter pub get
MIT License - Feel free to use this as a learning resource or starting point for your own MCP applications!