MCP server by thawndev
Code Quality Guardian MCP
Intelligent code quality guardian that fights vibecoding and enforces premium end-user experience. Built as a Model Context Protocol (MCP) server for GitHub Copilot CLI.
60+ detection rules across 5 engines: ESLint custom rules, AI slop pattern detection, UX excellence enforcement, security/perf gap analysis, and embedding-based semantic analysis.
What It Does
Three intelligence layers that turn LLM output into production-grade, premium software:
| Layer | Purpose | Example Catches |
|-------|---------|----------------|
| DEFEND | Stop bad code | Stubs, fakes, any escapes, XSS, eval, empty catch, lint suppression, emoji in JSX, inline styles, hardcoded secrets |
| ELEVATE | Enforce premium UX | Missing loading/empty/error states, no design tokens, bad touch targets, no dark mode, missing SafeAreaView, FlatList incomplete |
| GUIDE | Teach standards | Proactive preflight standards before writing code, premium patterns per framework |
| SEMANTIC | Deep analysis | Embedding-based detection of god components, poor error handling, missing validation, security risks via bge-small-en-v1.5 |
Tools (6)
| Tool | Description |
|------|-------------|
| analyze | Full codebase scan — all engines + quality score |
| quick_check | Fast pre-write gate — check code string before writing to file |
| get_standards | Quality reference — what premium apps look like |
| score | Quality scorecard — A+ to F grade with category breakdown |
| preflight | NEW Proactive standards — get requirements BEFORE writing a file |
| deep_analyze | NEW Semantic analysis — embedding-based anti-pattern detection |
Installation
cd code-quality-guardian-mcp
npm install
npm run build
Register with Copilot CLI
Add to ~/.config/github-copilot/mcp.json:
{
"mcpServers": {
"code-quality-guardian": {
"command": "node",
"args": ["/path/to/code-quality-guardian-mcp/dist/index.js"]
}
}
}
Custom Rules (DEFEND Layer — 10 ESLint + 20 Pattern Engine)
ESLint Custom Rules
| Rule | What It Catches | Severity |
|------|----------------|----------|
| no-emoji-in-code | Emoji characters in JSX — use icon libraries | error |
| no-inline-styles | style={{}} in JSX — use StyleSheet.create() | error |
| no-hardcoded-colors | Hex/RGB values — use design tokens | error |
| no-magic-numbers-strict | Unlabeled numeric literals | warning |
| no-hardcoded-strings-jsx | Raw strings in JSX — prep for i18n | warning |
| no-index-key | Array index as React key | error |
| no-raw-fetch | fetch() without error handling wrapper | warning |
| no-hardcoded-secrets | API keys, tokens, passwords in source | critical |
| naming-conventions | Functions must start with verb, booleans with is/has | warning |
| structure-limits | Too many useState/useEffect in one component | warning |
Pattern Engine (AI Slop Detection)
| Rule | What It Catches | Severity |
|------|----------------|----------|
| no-stub-implementation | Empty/TODO/throw functions — #1 vibecoding sin | error |
| no-fake-return | Math.random(), hardcoded arrays as return values | warning |
| no-placeholder-naming | foo, bar, temp, data, myVar | warning |
| no-commented-out-code | Dead code left as comments | warning |
| no-lint-suppression | @ts-nocheck, eslint-disable blankets | warning |
| no-skipped-tests | .skip, xit, test.todo | error |
| no-typescript-any | any type usage (counts all instances) | error |
| no-xss-vulnerability | dangerouslySetInnerHTML, innerHTML | critical |
| no-eval | eval(), new Function() | critical |
| no-empty-catch | catch(e) {} — silent failures | error |
| no-catch-only-log | catch(e) { console.log(e) } — not real handling | warning |
| no-bloat-imports | Full lodash/moment imports | warning |
| no-floating-promise | Unhandled promise (no await/catch/then) | warning |
Plus all standard ESLint rules: no-console, max-depth, max-lines, complexity, eqeqeq, prefer-const, etc.
UX Quality Checks (ELEVATE Layer)
| Check | What's Missing |
|-------|---------------|
| require-loading-state | Async op without loading UI |
| suggest-skeleton-loading | Spinner instead of skeleton loader |
| require-empty-state | List without empty state |
| require-error-state | Async op without error UI |
| require-error-boundary | Screen without ErrorBoundary |
| require-suspense-boundary | Lazy component without Suspense |
| require-design-tokens | Styles without theme reference |
| require-typography-scale | Font sizes off standard scale |
| enforce-spacing-system | Spacing not on 4pt/8pt grid |
| require-dark-mode-support | No color scheme awareness |
| require-safe-area | Screen without SafeAreaView (RN) |
| require-status-bar-config | No StatusBar configuration (RN) |
| require-keyboard-handling | TextInput without keyboard avoidance (RN) |
| require-press-feedback | Buttons without haptic/visual feedback (RN) |
| suggest-pull-to-refresh | Scrollable list without refresh (RN) |
Quality Score
OVERALL = weighted average:
Code Quality (25%) — DEFEND rules
UX Completeness (30%) — ELEVATE checks
Accessibility (20%) — WCAG compliance
Security (15%) — Zero tolerance (critical = F)
Performance (10%) — Optimization hints
Grades: A+ (95+) A (90+) B+ (85+) B (80+) C (70+) D (60+) F (<60)
Architecture
src/
├── index.ts # Entry + stdio transport + semantic warmup
├── server.ts # MCP server + 6 tools
├── types.ts # TypeScript interfaces
├── engine/
│ ├── eslint-engine.ts # ESLint v9 programmatic API
│ ├── pattern-engine.ts # AI slop detection (20+ rules)
│ ├── semantic-engine.ts # Embedding-based analysis (bge-small-en-v1.5)
│ └── score-engine.ts # Quality scoring algorithm
├── rules/ # 10 custom ESLint rules
├── elevate/ # UX quality checks
│ ├── state-completeness.ts # Loading/empty/error states
│ ├── ux-excellence.ts # Touch targets, FlatList, forms, modals
│ ├── design-system.ts # Tokens, typography, spacing
│ └── platform-polish.ts # SafeArea, StatusBar, keyboard
├── standards/ # Premium patterns + preflight
│ └── preflight.ts # Proactive file-type standards
├── profiles/ # Framework detection
└── formatters/ # Markdown output
Benchmark Results
| Test File | Findings | Grade |
|-----------|----------|-------|
| worst-code-ever.tsx (every anti-pattern) | 35 | F (54/100) |
| clean-code.tsx (well-written) | 1* | A+ (98/100) |
| bad-test.test.tsx (AI test sins) | 5 | — |
*1 finding is ESLint TS parser limitation for interface keyword outside TS config
License
MIT