Files
goodgo-platform/docs/audits/MCP_QUICK_REFERENCE_2.md
Ho Ngoc Hai 25b22ea9bd docs: move additional exploration docs to docs/audits/
Move 6 recently generated inquiry and MCP exploration documents
to the centralized audit directory.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-11 01:41:23 +07:00

4.4 KiB

MCP Module - Quick Reference & Testing Guide

📋 Module at a Glance

Aspect Details
Location apps/api/src/modules/mcp/
Total Files 4 source files
Test Files 1 test file (174 lines)
Architecture Presentation layer only
Testing Framework Vitest
Test Coverage Controller well tested

📁 Complete File Listing

MCP Module Files:
✅ index.ts (1 line)
✅ mcp.module.ts (22 lines)
✅ presentation/mcp-transport.controller.ts (102 lines)
✅ presentation/__tests__/mcp-transport.controller.spec.ts (174 lines)

🏗️ Architecture

Current (Simplified - Presentation Only)

Presentation Layer ✅
├── McpTransportController
│   ├── GET /mcp/servers
│   ├── GET /mcp/:serverName/sse  
│   └── POST /mcp/:serverName/messages
└── Tests (174 lines)

McpIntegrationModule (22 lines)
├── Module config
├── Service setup
└── Module lifecycle

Missing Layers (Not Implemented)

❌ Domain Layer (no entities, events, business logic)
❌ Application Layer (no handlers, commands, queries)
❌ Infrastructure Layer (no repositories, adapters)

🧪 Testing Overview

Test File: mcp-transport.controller.spec.ts (174 lines)

  • Total Tests: 11
  • Test Suites: 4 describe blocks
  • Coverage: 100% of controller endpoints

Test Breakdown

1. Security Decorators (4 tests)
   ├── JwtAuthGuard applied
   ├── listServers throttle (30 req/60s)
   ├── handleSse throttle (5 req/60s) ⚡ stricter
   └── handleMessage throttle (30 req/60s)

2. listServers (2 tests)
   ├── Returns server list
   └── Handles empty list

3. handleSse (3 tests)
   ├── Throws NOT_FOUND for missing server
   ├── Creates transport & connects
   └── Cleans up on connection close

4. handleMessage (2 tests)
   ├── Throws BAD_REQUEST for missing sessionId
   └── Throws NOT_FOUND for expired session

🎯 Key Classes

McpIntegrationModule

class McpIntegrationModule implements OnModuleInit {
  constructor(
    typesenseClient: TypesenseClientService,
    mcpRegistry: McpRegistryService,
    logger: LoggerService,
  ) {}
  
  async onModuleInit(): Promise<void> {
    // Set typesense client, re-initialize servers, log results
  }
}

McpTransportController

@Controller('mcp')
@UseGuards(JwtAuthGuard)
class McpTransportController {
  listServers(): { servers: string[] }
  
  async handleSse(serverName, user, req, res): Promise<void>
  
  async handleMessage(serverName, user, req, res): Promise<void>
}

🔧 Testing Patterns

Module Mocking

vi.mock('@goodgo/mcp-servers', () => ({
  SSEServerTransport: class MockSSE {
    sessionId = 'mock-session-id';
    handlePostMessage = vi.fn().mockResolvedValue(undefined);
  },
}));

Service Mocking

mockRegistry = {
  getServerNames: vi.fn(),
  getServer: vi.fn(),
};

Decorator Verification

const guards = Reflect.getMetadata('__guards__', McpTransportController);
const throttleLimit = Reflect.getMetadata('THROTTLER:LIMITdefault', method);

📚 Testing Examples from Other Modules

Auth Module Pattern (Simple)

  • Minimal dependencies
  • Direct handler instantiation
  • Focus on behavior verification

Payments Module Pattern (Complex)

  • Multiple dependency mocks
  • Business rule testing
  • Event bus verification

Domain Entity Pattern

  • Explicit vitest imports
  • State transition testing
  • Domain event verification
  • Error handling with Result types

Infrastructure Pattern

  • External service simulation
  • Security testing (crypto)
  • Complex test data builders

🚀 Running Tests

# Run all MCP tests
pnpm test -- src/modules/mcp

# Run with watch
pnpm test -- --watch src/modules/mcp

# Run with coverage
pnpm test -- --coverage src/modules/mcp

# Run specific test
pnpm test -- src/modules/mcp/presentation/__tests__/mcp-transport.controller.spec.ts

💡 Recommendations

High Priority

  • Controller is well tested - maintain this
  • 📝 Add tests for McpIntegrationModule.onModuleInit()
  • 📝 Test module dependency injection

Lower Priority

  • 🏗️ If domain logic added, follow payments patterns
  • 🏗️ If handlers added, use CQRS patterns
  • 🏗️ Add integration tests for SSE lifecycle