Move 6 recently generated inquiry and MCP exploration documents to the centralized audit directory. Co-Authored-By: Paperclip <noreply@paperclip.ing>
7.0 KiB
7.0 KiB
MCP Module Exploration - GoodGo Platform
1. MODULE STRUCTURE & SOURCE FILES
Directory Structure
apps/api/src/modules/mcp/
├── index.ts
├── mcp.module.ts
└── presentation/
├── mcp-transport.controller.ts
└── __tests__/
└── mcp-transport.controller.spec.ts
All Source Files (4 files)
1. apps/api/src/modules/mcp/index.ts
- Type: Module entry point (exports)
- Lines: 1
- Purpose: Exports the McpIntegrationModule
- Exports:
{ McpIntegrationModule }
2. apps/api/src/modules/mcp/mcp.module.ts
- Type: NestJS Module configuration (22 lines)
- Key Class:
McpIntegrationModule implements OnModuleInit - Responsibility:
- Sets up MCP core module with configuration
- Initializes TypesenseClient for MCP registry
- Logs initialized server names on module init
- Dependencies Injected:
TypesenseClientService(from SearchModule)McpRegistryService(from @goodgo/mcp-servers)LoggerService(from SharedModule)
- Imports: SearchModule, AuthModule, McpCoreModule.forRoot()
- Controllers: McpTransportController
- Lifecycle: Implements
onModuleInit()
3. apps/api/src/modules/mcp/presentation/mcp-transport.controller.ts
- Type: NestJS Controller (102 lines)
- Key Class:
McpTransportController - Responsibility: HTTP transport layer for MCP SSE connections
- Decorators: @ApiTags, @ApiBearerAuth, @Controller, @UseGuards(JwtAuthGuard)
- Properties:
transports: Map<string, SSEServerTransport>(session management) - Injected:
registry: McpRegistryService
Endpoints:
- GET /mcp/servers - List available MCP servers (Throttle: 30/60s)
- GET /mcp/:serverName/sse - Open SSE connection (Throttle: 5/60s, stricter)
- POST /mcp/:serverName/messages - Send message to session (Throttle: 30/60s)
4. apps/api/src/modules/mcp/presentation/tests/mcp-transport.controller.spec.ts
- Type: Unit Test Suite (174 lines)
- Framework: Vitest
- Tests: 11 total in 4 describe blocks
- Coverage: Security decorators, listServers, handleSse, handleMessage
2. TEST FILES SUMMARY
Total: 1 test file (174 lines)
File: mcp-transport.controller.spec.ts
- Suites: 4 describe blocks
- Total Tests: 11
- Status: ✅ Well tested
- Coverage: Controller endpoints, security, error handling
3. DDD LAYER STRUCTURE
Current Status: SIMPLIFIED (Presentation-only)
✅ What EXISTS:
- Presentation Layer
presentation/mcp-transport.controller.ts(102 lines)presentation/__tests__/mcp-transport.controller.spec.ts(174 lines)
❌ What DOES NOT EXIST:
- Domain Layer - No entities, value objects, events
- Application Layer - No handlers, commands, queries
- Infrastructure Layer - No repositories, adapters
Architecture Notes:
- Acts as integration wrapper for @goodgo/mcp-servers
- Simple HTTP-to-SSE bridge
- In-memory session tracking via Map
- No business logic or persistence
4. KEY CLASSES/HANDLERS
McpIntegrationModule
- Status: ⚠️ Partially tested
- Methods: constructor, onModuleInit()
- Tests Needed: Module initialization, service integration
McpTransportController
- Status: ✅ Well tested
- Methods: listServers(), handleSse(), handleMessage()
- Tests: 11 comprehensive tests covering all methods
5. TESTING PATTERNS FROM OTHER MODULES
Pattern 1: Auth Module (Simple Handler)
describe('LoginUserHandler', () => {
let handler: LoginUserHandler;
let mockTokenService = { generateTokenPair: vi.fn() };
beforeEach(() => {
handler = new LoginUserHandler(mockTokenService as any);
});
it('generates token pair', async () => {
mockTokenService.generateTokenPair.mockResolvedValue(tokenPair);
const result = await handler.execute(command);
expect(result).toEqual(tokenPair);
});
});
Pattern 2: Payments Module (Complex Handler)
describe('CreatePaymentHandler', () => {
let handler: CreatePaymentHandler;
let mockPaymentRepo: { [K in keyof IPaymentRepository]: ReturnType<typeof vi.fn> };
let mockGatewayFactory: { getGateway: ReturnType<typeof vi.fn> };
beforeEach(() => {
mockPaymentRepo = {
findById: vi.fn(),
save: vi.fn().mockResolvedValue(undefined),
};
handler = new CreatePaymentHandler(mockPaymentRepo as any, mockGatewayFactory as any);
});
it('creates payment successfully', async () => {
const result = await handler.execute(command);
expect(result.paymentId).toBeDefined();
expect(mockPaymentRepo.save).toHaveBeenCalledTimes(1);
});
});
Pattern 3: Domain Entity Testing
import { describe, it, expect } from 'vitest';
describe('PaymentEntity', () => {
it('should create payment with events', () => {
const payment = PaymentEntity.createNew(...);
expect(payment.status).toBe('PENDING');
expect(payment.domainEvents).toHaveLength(1);
expect(payment.domainEvents[0]).toBeInstanceOf(PaymentCreatedEvent);
});
});
Pattern 4: Infrastructure Service Testing
describe('ZalopayService', () => {
let service: ZalopayService;
beforeEach(() => {
const mockConfig = {
get: vi.fn((key) => env[key]),
getOrThrow: vi.fn((key) => env[key] || throw),
};
service = new ZalopayService(mockConfig as any);
});
it('should verify valid callback', () => {
const mac = crypto.createHmac('sha256', key2).update(dataStr).digest('hex');
const result = service.verifyCallback({ data: dataStr, mac });
expect(result.isValid).toBe(true);
});
});
6. TESTING CONVENTIONS SUMMARY
Framework & Setup
- Framework: Vitest
- Environment: Node.js
- Globals: Enabled
- File Pattern:
*.spec.ts - Test Organization:
__tests__/subdirectory
Mocking Patterns
- Service Mocks:
mockService = { method: vi.fn().mockResolvedValue(value) } - Module Mocks:
vi.mock('@goodgo/mcp-servers', () => ({ ... })) - Configuration Mocks:
get: vi.fn((key) => env[key])
Test Structure
describe('ClassName', () => {
let instance: ClassName;
let mockDep1: Mock;
beforeEach(() => {
mockDep1 = { method: vi.fn() };
instance = new ClassName(mockDep1 as any);
});
describe('methodName', () => {
it('happy path', async () => {
mockDep1.method.mockResolvedValue(expected);
const result = await instance.method();
expect(result).toEqual(expected);
});
});
});
Test Commands
# Run MCP tests
pnpm test -- src/modules/mcp
# Watch mode
pnpm test -- --watch src/modules/mcp
# With coverage
pnpm test -- --coverage src/modules/mcp
7. RECOMMENDATIONS
Immediate
- ✅ Maintain controller test coverage
- 📝 Add tests for McpIntegrationModule.onModuleInit()
- 📝 Test module dependency injection
Future
- 🏗️ Add integration tests for full SSE lifecycle
- 🏗️ If domain logic added, follow payments module pattern
- 🏗️ If handlers added, use CQRS patterns from auth/payments modules