flutter-ui-safety-gate
v1.0.0
Published
Flutter UI Safety Gate — AI-native code quality enforcer for Flutter projects. Plug into Claude, Cursor or any MCP-compatible tool to catch layout bugs, memory leaks and null safety violations before they ship.
Maintainers
Readme
Flutter UI Safety Gate
A Model Context Protocol (MCP) server that enforces Flutter UI layout safety, null safety, and code quality rules — directly inside your AI coding tool.
Works with Claude, Cursor, Windsurf, VS Code and any MCP-compatible AI tool. Includes a one-time global git pre-commit hook that protects all your projects automatically.
Features
| Tool | Description |
|---|---|
| analyze_file | Scan a single Dart file for layout & null safety violations |
| analyze_project | Scan an entire Flutter project recursively |
| check_git_diff | Check only staged files before committing |
| auto_fix_issues | Auto-repair common layout bugs and unsafe casts |
| generate_report | Generate a markdown QA report with Project Health Index |
| ai_review_file | AI-powered deep code review via OpenRouter |
| ai_review_project | AI-powered review of entire project |
| generate_model_class | Generate Dart model classes from JSON or API endpoint |
| setup_global_git_hook | Install a global pre-commit hook for all git projects |
Rules Enforced
Layout & Crash Risks
INVALID_EXPANDED_PARENT— Expanded/Flexible outside Row/Column/FlexPOSITIONED_OUTSIDE_STACK— Positioned outside StackSPACER_OUTSIDE_FLEX— Spacer outside Row/Column/FlexSPACER_INSIDE_SCROLLVIEW— Spacer inside scrollable (unbounded height)FLEX_CHILD_VIEWPORT— ListView/GridView inside Flex without Expanded or shrinkWrapNESTED_VIEWPORTS— Scrollable inside scrollable without shrinkWrap + NeverScrollableScrollPhysicsINFINITE_ASPECT_RATIO— AspectRatio inside scroll view without constraintsTEXT_OVERFLOW_IN_FLEX— Text in Row without Expanded or overflow handlingHARDCODED_SIZES— Width/height values > 320 hardcoded (screen overflow risk)
Null & Type Safety
FORCE_UNWRAP— Force-unwrap operator!usageUNSAFE_CAST— Unsafeas Typecast without null checkUNINITIALIZED_LATE_VAR—latevariable declared without initialization
Memory Leaks
UNDISPOSED_CONTROLLER— TextEditingController, ScrollController etc. never disposedUNDISPOSED_FOCUS_NODE— FocusNode never disposedUNCLOSED_STREAM_CONTROLLER— StreamController never closed
Performance
SETSTATE_IN_SCROLL_LISTENER— setState inside scroll/animation listenerCONTROLLER_INSTANTIATED_IN_BUILD— Controller instantiated inside build()ASYNC_AWAIT_UNMOUNTED— setState after await without mounted checkMISSING_CONST_CONSTRUCTOR— Missingconston constant widgetsDEEP_WIDGET_TREE— Widget tree depth exceeds 8 levelsSTATELESS_CANDIDATE— StatefulWidget that never calls setStateMEDIA_QUERY_OVERHEAD— MediaQuery.of(context) triggering excess rebuilds
Code Quality
HARDCODED_UI_STRING— Hardcoded strings in Text widget (i18n smell)HARDCODED_THEME_VALUES— Colors/TextStyle hardcoded instead of Theme.of(context)MISSING_WIDGET_KEY— Widget constructor missingkeyparameterUNUSED_IMPORTS_VARIABLES— Private variables or import aliases never usedAVOID_PRINT— Raw print() used instead of debugPrint()MISSING_ASSET_DECLARATION— Asset referenced but not declared in pubspec.yamlMISSING_ASSET_FILE— Asset file referenced but does not exist on diskUNSAFE_NAVIGATOR_POP— Navigator.pop called after await without mounted check
Installation
1. Clone the repository
git clone https://github.com/YOUR_USERNAME/flutter-ui-safety-gate.git
cd flutter-ui-safety-gate2. Install dependencies
npm install3. Configure environment
cp .env.example .envOpen .env and add your OpenRouter API key:
OPENROUTER_API_KEY=your_openrouter_api_key_here
OPENROUTER_MODEL=anthropic/claude-3.5-sonnetGet a free API key at openrouter.ai
Setup in Your AI Tool
Claude Desktop / Claude Code
Add to your claude_desktop_config.json:
{
"mcpServers": {
"flutter-ui-safety-gate": {
"command": "node",
"args": ["/absolute/path/to/flutter-ui-safety-gate/server.js"]
}
}
}Cursor
Add to ~/.cursor/mcp.json:
{
"mcpServers": {
"flutter-ui-safety-gate": {
"command": "node",
"args": ["/absolute/path/to/flutter-ui-safety-gate/server.js"]
}
}
}Windsurf
Add to Windsurf MCP settings:
{
"mcpServers": {
"flutter-ui-safety-gate": {
"command": "node",
"args": ["/absolute/path/to/flutter-ui-safety-gate/server.js"]
}
}
}Global Git Pre-commit Hook
Run this once from any AI tool to protect all your git projects automatically:
setup_global_git_hookThis will:
- Create
~/.git-hooks/pre-commit - Set
git config --global core.hooksPath ~/.git-hooks - Check staged Dart files on every
git commit— in any project, any editor, any AI tool
What the hook does on each commit:
git commit
↓
Pre-commit hook fires automatically
↓
Checks all staged .dart files using Safety Gate rules
↓
Blockers found? → Commit BLOCKED with details
All clear? → Commit proceeds normallyNo API key or internet connection required for the hook — it runs the analyzer locally via Node.js.
Usage Examples
Analyze a single file
analyze_file with filePath: "lib/screens/home_screen.dart"Analyze entire project
analyze_project with projectPath: "."Check staged files before commit
check_git_diff with projectPath: "."Auto-fix a file
auto_fix_issues with filePath: "lib/widgets/my_widget.dart"Generate a Dart model from JSON
generate_model_class with jsonInput: '{"id":1,"name":"John"}' and className: "UserModel"Generate a Dart model from API endpoint
generate_model_class with jsonInput: "https://api.example.com/users/1" and className: "UserResponse"AI-powered review
ai_review_file with filePath: "lib/screens/checkout_screen.dart"Project Structure
flutter-ui-safety-gate/
├── server.js # MCP server entry point
├── src/
│ ├── analyzer/ # Core static analysis engine
│ │ ├── index.js # Dart file & directory analyzer
│ │ └── rules.js # All rule definitions
│ ├── autofix/ # Auto-fix engine
│ ├── ai-review/ # OpenRouter AI review integration
│ ├── hooks/
│ │ └── check-staged.js # Git pre-commit hook runner
│ └── utils/
│ ├── formatter.js # JSON & markdown formatters
│ ├── generator.js # Dart model class generator
│ └── docParser.js # API/Swagger doc parser
├── .env.example # Environment variable template
└── package.jsonRequirements
- Node.js 18+
- Git (for pre-commit hook features)
- OpenRouter API key (only for
ai_review_fileandai_review_projecttools)
License
ISC
