Files
Andris Enins 91cd18aec6 feat: initial implementation — all 35 requirements across phases 1-3
Backend (Spring Boot 3.2 / Java 21 / PostgreSQL):
- JWT auth with BCrypt password hashing
- User profile + Mifflin-St Jeor BMR calculator
- Food search + barcode via OpenFoodFacts API with local cache
- Meal CRUD with user data isolation and ownership checks
- AI photo analysis (OpenAI Vision) with confidence intervals
- AI correction feedback loop for personalisation
- Flyway DB migrations + RFC-7807 error responses

Mobile (React Native / TypeScript):
- Full navigation stack (Auth → Tabs → Home stack)
- Design tokens (WCAG 2.2 AA colours, 8px grid, 48px touch targets)
- 10 screens: Login, Register, Home, Search, Camera, AI Result, Edit Meal,
  Daily Details, History, Profile
- Confidence-aware calorie display (kcal ± range)
- Repeat last meal shortcut + macro tracking

Docs:
- docs/PLAN-AND-REQUIREMENTS.md
- docs/traceability.csv (35 requirements, all Implemented)
2026-05-18 21:56:13 +03:00

14 KiB

All MCP tools use stdio transport. Every tool validates input with Zod before processing.

MCP Standards - Layer 2

Module: MCP Standards Component: Layer 2 (Model Context Protocol Server) Load: When working on virsaitis-development/virsaitis-mcp/ Version: 3.0.0 Updated: 2026-04-20


🎯 Purpose

Defines TypeScript standards, MCP SDK usage, and development workflow for Virsaitis MCP Server (Layer 2 governance enforcement).


🤖 Machine Policy

[TECHNOLOGY_STACK]
LANGUAGE=TypeScript 5.0+
RUNTIME=Node.js 18+
FRAMEWORK=@modelcontextprotocol/sdk
BUILD=tsc + esbuild
TEST=vitest
LINT=eslint + prettier

[CODE_STANDARDS]
INDENTATION=2_spaces
LINE_LENGTH=100_chars
QUOTES=single
SEMICOLONS=required
TRAILING_COMMAS=required_multiline

[QUALITY_GATES]
BUILD=must_succeed
TESTS=must_pass
LINT=zero_errors
TYPE_CHECK=strict_mode
COVERAGE=70_percent_min

📐 TypeScript Standards (TIER-1)

Indentation & Formatting

REQUIRED:

  • Indentation: 2 spaces (not 4, not tabs)
  • Line length: 100 characters maximum
  • Quotes: Single quotes 'string' for strings
  • Semicolons: Required at end of statements
  • Trailing commas: Required for multiline arrays/objects

GOOD:

const config = {
  server: 'virsaitis-mcp',
  port: 3000,
  enabled: true,
};

BAD:

const config = {
    server: "virsaitis-mcp",
    port: 3000,
    enabled: true
}  // Missing trailing comma, 4 spaces, double quotes

File Organization

STANDARD ORDER:

// 1. External imports (Node.js, npm packages)
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import * as fs from 'fs';

// 2. Internal imports (project files)
import { GovernanceValidator } from './governance/validator.js';
import { PolicyEngine } from './policy/engine.js';

// 3. Type definitions
interface ValidationResult {
  allowed: boolean;
  reason?: string;
}

// 4. Constants
const PROTECTED_PATTERNS = [
  '.github/copilot-instructions.md',
  'requirements/**',
];

// 5. Class/function implementations
export class VirsaitisMCPServer {
  // Implementation
}

Naming Conventions (TIER-1)

Element Convention Example
Classes PascalCase GovernancePolicyValidator
Interfaces PascalCase PolicyResult or IPolicyResult
Types PascalCase OperationType
Functions camelCase validateFileOperation
Methods camelCase checkPermissions
Variables camelCase isValid, fileName
Constants UPPER_SNAKE_CASE MAX_RETRIES, PROTECTED_PATTERNS
Private members Leading underscore _config, _cache
Enums PascalCase TierLevel
Enum values PascalCase TierLevel.Critical

🔧 MCP Server Architecture

Server Structure

virsaitis-development/virsaitis-mcp/
├── src/
│   ├── index.ts                    (server entry point)
│   ├── server.ts                   (MCP server class)
│   ├── governance/
│   │   ├── types.ts                (TierLevel, GovernanceRule, ValidationResult)
│   │   ├── patterns.ts             (glob pattern matching)
│   │   ├── cache.ts                (in-memory governance cache)
│   │   ├── loader.ts               (parse core-policies.md + agent files)
│   │   └── validator.ts            (GovernanceValidator - TIER validation)
│   ├── config.ts                   (server configuration - REQ-MCP-010)
│   ├── tools/
│   │   ├── scan-secrets.ts         (mcp_virsaitis_scan_secrets)
│   │   ├── validate-path.ts        (mcp_virsaitis_validate_path)
│   │   ├── validate-command.ts     (mcp_virsaitis_validate_command)
│   │   ├── audit-logger.ts         (mcp_virsaitis_read_audit_log)
│   │   └── iteration-complete.ts   (mcp_virsaitis_iteration_complete)
├── tests/
│   ├── unit/
│   ├── integration/
│   └── fixtures/
├── build/                           (compiled output)
├── package.json
├── tsconfig.json
├── vitest.config.ts
└── README.md

MCP Tools Implementation

TOOL PATTERN:

// Tool definition
server.setRequestHandler(ToolsListRequestSchema, async () => {
  return {
    tools: [
      {
        name: 'mcp_virsaitis_validate_operation',
        description: 'Validates if an operation is allowed by governance policy',
        inputSchema: {
          type: 'object',
          properties: {
            operation: {
              type: 'string',
              description: 'Operation type: read, write, delete, execute',
            },
            filePath: {
              type: 'string',
              description: 'Absolute file path',
            },
          },
          required: ['operation', 'filePath'],
        },
      },
    ],
  };
});

// Tool execution
server.setRequestHandler(ToolCallRequestSchema, async (request) => {
  if (request.params.name === 'mcp_virsaitis_validate_operation') {
    const { operation, filePath } = request.params.arguments;

    // Validation logic
    const result = await governanceValidator.validate(operation, filePath);

    return {
      content: [
        {
          type: 'text',
          text: JSON.stringify(result, null, 2),
        },
      ],
    };
  }
});

CHECKPOINT — Is this MCP tool using Zod input validation? Every tool parameter must have a schema.

Type Safety (TIER-1)

TypeScript Configuration

tsconfig.json REQUIREMENTS:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ES2022",
    "moduleResolution": "node",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": false,
    "forceConsistentCasingInFileNames": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "outDir": "./build",
    "rootDir": "./src"
  }
}

STRICT MODE REQUIRED:

  • strict: true (enables all strict checks)
  • noImplicitAny: true (no implicit any types)
  • strictNullChecks: true (null/undefined handling)
  • strictFunctionTypes: true (function type checking)
  • strictPropertyInitialization: true (class property init)

Explicit Type Annotations

REQUIRED FOR:

  • Public function return types
  • Public method return types
  • Exported interfaces/types
  • Complex function parameters

GOOD:

export function validateTier(tier: string): boolean {
  return ['TIER-0', 'TIER-1', 'TIER-2', 'TIER-3'].includes(tier);
}

export interface PolicyResult {
  allowed: boolean;
  tier: string;
  reason?: string;
  consequences?: Consequence[];
}

BAD:

export function validateTier(tier) {  // Missing parameter type
  return ['TIER-0', 'TIER-1', 'TIER-2', 'TIER-3'].includes(tier);
}  // Missing return type

export interface PolicyResult {
  allowed;  // Missing type
  tier;     // Missing type
}

🧪 Testing Standards (TIER-1)

Test Framework

USING: Vitest (fast, TypeScript-native)

vitest.config.ts:

import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    coverage: {
      provider: 'v8',
      reporter: ['text', 'html', 'lcov'],
      lines: 70,
      functions: 70,
      branches: 70,
      statements: 70,
    },
  },
});

Test Structure

PATTERN:

import { describe, it, expect, beforeEach } from 'vitest';
import { GovernanceValidator } from '../src/governance/validator';

describe('GovernanceValidator', () => {
  let validator: GovernanceValidator;

  beforeEach(() => {
    validator = new GovernanceValidator();
  });

  describe('validateFileOperation', () => {
    it('should block protected file modification', () => {
      // Given
      const operation = 'write';
      const filePath = '.github/copilot-instructions.md';

      // When
      const result = validator.validateFileOperation(operation, filePath);

      // Then
      expect(result.allowed).toBe(false);
      expect(result.tier).toBe('TIER-0');
      expect(result.reason).toContain('protected file');
    });

    it('should allow non-protected file modification', () => {
      // Given
      const operation = 'write';
      const filePath = 'src/my-file.ts';

      // When
      const result = validator.validateFileOperation(operation, filePath);

      // Then
      expect(result.allowed).toBe(true);
    });
  });
});

Test Coverage Requirements

MINIMUM COVERAGE:

  • Overall: 70%
  • Security-critical code: 100%
  • Governance validation: 100%
  • Consequence evaluation: 100%
  • Tool implementations: 90%
  • Utilities: 70%

MEASURE:

npm run test:coverage

🔒 Security Standards

Input Validation

ALWAYS VALIDATE:

function validateFilePath(filePath: string): string {
  // Check for null/undefined
  if (!filePath) {
    throw new Error('File path is required');
  }

  // Check for path traversal
  if (filePath.includes('..')) {
    throw new Error('Path traversal detected');
  }

  // Normalize path
  const normalized = path.normalize(filePath);

  // Ensure absolute path
  if (!path.isAbsolute(normalized)) {
    throw new Error('Absolute path required');
  }

  return normalized;
}
```\n\n> \u26a1 CHECKPOINT \u2014 MCP uses stdio transport only. If you see HTTP fetch or REST endpoints, that code is wrong.\n\n### Error Handling", "oldString": "```\n\n### Error Handling
- Internal file paths in error messages
- Sensitive configuration
- Stack traces to external systems
- Credentials or secrets

 **GOOD**:
```typescript
try {
  await fs.promises.readFile(filePath);
} catch (error) {
  // Log full error internally
  logger.error('File read failed', { filePath, error });

  // Return sanitized error to user
  return {
    success: false,
    message: 'Unable to read file',
  };
}

BAD:

try {
  await fs.promises.readFile(filePath);
} catch (error) {
  // Exposes internal path
  return {
    success: false,
    message: `Failed to read ${filePath}: ${error.message}`,
  };
}

🔄 Build & Development Workflow

Development Commands

# Install dependencies
npm install

# Start development with file watching
npm run dev

# Build TypeScript
npm run build

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Run linter
npm run lint

# Fix linting issues
npm run lint:fix

# TypeScript type checking
npm run type-check

# Format code
npm run format

Before Commit Checklist (TIER-1)

ALL MUST PASS:

npm run build       # ✅ Must succeed
npm test            # ✅ Must pass (all tests)
npm run lint        # ✅ Zero errors
npm run type-check  # ✅ No type errors
npm run test:coverage  # ✅ Coverage ≥70%

IF ANY FAIL: Fix before committing


📦 MCP Server Packaging

Build Output

COMPILED TO: build/ directory

INCLUDES:

  • build/index.js (entry point)
  • build/**/*.js (compiled TypeScript)
  • build/**/*.d.ts (type definitions)
  • build/**/*.js.map (source maps)

NPM Package

package.json ESSENTIALS:

{
  "name": "@virsaitis/mcp-server",
  "version": "2.0.0",
  "type": "module",
  "main": "./build/index.js",
  "types": "./build/index.d.ts",
  "bin": {
    "virsaitis-mcp": "./build/index.js"
  },
  "engines": {

---

## Key Rules From This Module

- stdio transport only. No HTTP REST endpoints for MCP communication.
- Every tool input validated with Zod schemas before processing.
- TypeScript strict mode. No `any` types without documented justification.
- All dependencies must be in DEPENDENCY-REGISTER.md before use.
- Definitions: `.github/virsaitis-definition-library.md`

Return to hub: `.github/copilot-instructions.md`
    "node": ">=18.0.0"
  },
  "scripts": {
    "build": "tsc && esbuild",
    "test": "vitest run",
    "test:coverage": "vitest run --coverage",
    "lint": "eslint src/",
    "type-check": "tsc --noEmit"
  }
}

CHECKPOINT — All dependencies approved? Check virsaitis-mcp/DEPENDENCY-REGISTER.md before adding packages.

🔗 Integration with Agent & Extension

Agent → MCP Communication

Agent calls MCP tools:

[Agent.md instruction]
Before editing protected file, call mcp_virsaitis_validate_operation tool.
Tool returns whether operation allowed.
If not allowed, respond with TIER-0 VIOLATION PREVENTED.

MCP response format:

interface ValidationResponse {
  allowed: boolean;
  tier: 'TIER-0' | 'TIER-1' | 'TIER-2' | 'TIER-3';
  reason?: string;
  consequences?: {
    operation: string;
    userImpact: string;
    technicalImpact: string;
    businessImpact: string;
    remediation: string;
  };
}

MCP ← Extension Communication

Extension queries MCP:

  • User tries to edit file
  • Extension calls mcp_virsaitis_validate_operation
  • MCP validates against governance
  • Extension shows 🛡️ shield if protected
  • Extension blocks action if TIER-0

💡 Best Practices

Code Organization

ONE CONCERN PER FILE:

  • Each file handles one specific responsibility
  • Validators in governance/
  • Tools in tools/
  • Utilities in utils/

SMALL FUNCTIONS:

  • Keep functions <50 lines
  • Single responsibility
  • Testable in isolation

AVOID GOD CLASSES:

  • Break large classes into smaller components
  • Use composition over inheritance
  • Inject dependencies

Performance

CACHING:

class GovernanceCache {
  private _rulesCache: Map<string, Rule[]> = new Map();
  private _cacheExpiry = 5 * 60 * 1000; // 5 minutes

  async getRules(category: string): Promise<Rule[]> {
    const cached = this._rulesCache.get(category);
    if (cached && !this.isExpired(cached)) {
      return cached;
    }

    const rules = await this.loadRules(category);
    this._rulesCache.set(category, rules);
    return rules;
  }
}

📚 Quick Reference

Aspect Standard Command
Indentation 2 spaces ESLint enforces
Build tsc + esbuild npm run build
Test Vitest npm test
Coverage ≥70% npm run test:coverage
Lint ESLint + Prettier npm run lint
Type Check TypeScript strict npm run type-check

MCP Standards Module v3.0.0 TypeScript governance enforcement server