Move 6 recently generated inquiry and MCP exploration documents to the centralized audit directory. Co-Authored-By: Paperclip <noreply@paperclip.ing>
4.4 KiB
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