This guide consolidates all code quality, linting, and architectural compliance information for the XcodeBuildMCP project.
- Overview
- ESLint Configuration
- Architectural Rules
- Development Scripts
- Code Pattern Violations
- Type Safety Migration
- Best Practices
XcodeBuildMCP enforces code quality through multiple layers:
- ESLint: Handles general code quality, TypeScript rules, and stylistic consistency
- TypeScript: Enforces type safety with strict mode
- Pattern Checker: Enforces XcodeBuildMCP-specific architectural rules
- Migration Scripts: Track progress on type safety improvements
The project uses a comprehensive ESLint setup that covers:
- TypeScript type safety rules
- Code style consistency
- Import ordering
- Unused variable detection
- Testing best practices
For detailed ESLint rules and rationale, see ESLINT_TYPE_SAFETY.md.
# Check for linting issues
npm run lint
# Auto-fix linting issues
npm run lint:fixXcodeBuildMCP enforces several architectural patterns that cannot be expressed through ESLint:
Rule: All tools must use dependency injection for external interactions.
✅ Allowed:
createMockExecutor()for command execution mockingcreateMockFileSystemExecutor()for file system mocking- Logic functions accepting
executor?: CommandExecutorparameter
❌ Forbidden:
- Direct calls to
execSync,spawn, orexecin production code - Testing handler functions directly
- Real external side effects in unit tests (xcodebuild/xcrun/filesystem writes outside mocks)
Rule: MCP handlers must have exact signatures as required by the SDK.
✅ Tool Handler Signature:
async handler(args: Record<string, unknown>): Promise<ToolResponse>✅ Resource Handler Signature:
async handler(uri: URL): Promise<{ contents: Array<{ text: string }> }>❌ Forbidden:
- Multiple parameters in handlers
- Optional parameters
- Dependency injection parameters in handlers
Rule: Tests must only call logic functions, never handlers directly.
✅ Correct Pattern:
const result = await myToolLogic(params, mockExecutor);❌ Forbidden Pattern:
const result = await myTool.handler(params);Rule: MCP server instances must use proper SDK types, not generic casts.
✅ Correct Pattern:
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
const server = (globalThis as { mcpServer?: McpServer }).mcpServer;
server.server.createMessage({...});❌ Forbidden Pattern:
const server = (globalThis as { mcpServer?: Record<string, unknown> }).mcpServer;
const serverInstance = (server.server ?? server) as Record<string, unknown> & {...};# Build the project
npm run build
# Run type checking
npm run typecheck
# Run tests
npm run test
# Check code patterns (architectural compliance)
node scripts/check-code-patterns.js
# Check type safety migration progress
npm run check-migrationThe pattern checker enforces XcodeBuildMCP-specific architectural rules:
# Check all patterns
node scripts/check-code-patterns.js
# Check specific pattern type
node scripts/check-code-patterns.js
node scripts/check-code-patterns.js --pattern=execsync
node scripts/check-code-patterns.js --pattern=handler
node scripts/check-code-patterns.js --pattern=handler-testing
node scripts/check-code-patterns.js --pattern=server-typing
# Get help
node scripts/check-code-patterns.js --help# Show tool and resource summary
npm run tools
# List all tools
npm run tools:list
# List both tools and resources
npm run tools:allThe pattern checker identifies the following violations:
What: Tests that mock external side effects without injected executors/filesystem dependencies
Why: Breaks deterministic external-boundary testing
Fix: Use createMockExecutor() / createMockFileSystemExecutor() for external dependencies
What: Direct use of Node.js child_process functions in production code
Why: Bypasses CommandExecutor dependency injection
Fix: Accept CommandExecutor parameter and use it
What: Handlers with incorrect parameter signatures Why: MCP SDK requires exact signatures Fix: Move dependencies inside handler body
What: Tests calling .handler() directly
Why: Violates dependency injection principle
Fix: Test logic functions instead
What: Casting MCP server instances to Record<string, unknown> or using custom interfaces instead of SDK types
Why: Breaks type safety and prevents proper API usage
Fix: Import McpServer from SDK and use proper typing instead of generic casts
The project is migrating to improved type safety using the createTypedTool factory:
# Show summary
npm run check-migration
# Show detailed analysis
npm run check-migration:verbose
# Show only unmigrated tools
npm run check-migration:unfixed- Compile-time type safety for tool parameters
- Automatic Zod schema validation
- Better IDE support and autocomplete
- Consistent error handling
Always run these checks before committing:
npm run build # Ensure code compiles
npm run typecheck # Check TypeScript types
npm run lint # Check linting rules
npm run test # Run tests
node scripts/check-code-patterns.js # Check architectural compliance- Use dependency injection pattern
- Follow handler signature requirements
- Create comprehensive tests (test logic, not handlers)
- Use
createTypedToolfactory for type safety - Document parameter schemas clearly
- Import the logic function, not the default export
- Use
createMockExecutor()/createMockFileSystemExecutor()for external side effects - Test three dimensions: validation, command generation, output processing
- Never test handlers directly
- Keep tools in appropriate workflow directories
- Share common tools via
-shareddirectories - Re-export shared tools, don't duplicate
- Follow naming conventions for tools
The project uses multiple layers of automated enforcement:
- Pre-commit: ESLint and TypeScript checks (if configured)
- CI Pipeline: All checks run on every PR
- PR Blocking: Checks must pass before merge
- Code Review: Automated and manual review processes
If ESLint reports false positives in test files, check that:
- Test files are properly configured in
.eslintrc.json - Test-specific rules are applied correctly
- File patterns match your test file locations
If the pattern checker reports unexpected violations:
- Check if it's a legitimate architectural violation
- Verify the file is in the correct directory
- Ensure you're using the latest pattern definitions
If migration tooling reports incorrect status:
- Ensure the tool exports follow standard patterns
- Check that schema definitions are properly typed
- Verify the handler uses the schema correctly
- Automated Fixes: Add auto-fix capability to pattern checker
- IDE Integration: Create VS Code extension for real-time checking
- Performance Metrics: Add build and test performance tracking
- Complexity Analysis: Add code complexity metrics
- Documentation Linting: Add documentation quality checks