Some checks failed
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 29s
CI / E2E Tests (push) Has been skipped
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 2m42s
Deploy / Build Web Image (push) Failing after 27s
Deploy / Build AI Services Image (push) Failing after 29s
E2E Tests / Playwright E2E (push) Failing after 43s
Deploy / Build API Image (push) Failing after 1m31s
Security Scanning / Dependency Audit (pnpm) (push) Failing after 6s
Security Scanning / Trivy Scan — API Image (push) Failing after 5m35s
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 3m45s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Smoke Test Staging (push) Has been skipped
Deploy / Deploy to Production (push) Has been skipped
Deploy / Smoke Test Production (push) Has been skipped
Deploy / Rollback Staging (push) Has been skipped
Deploy / Rollback Production (push) Has been skipped
Security Scanning / Trivy Scan — Web Image (push) Failing after 13m51s
Security Scanning / Trivy Filesystem Scan (push) Failing after 14m46s
Security Scanning / Security Gate (push) Has been cancelled
237 lines
7.8 KiB
Markdown
237 lines
7.8 KiB
Markdown
# Khám Phá Module MCP - Nền Tảng GoodGo
|
|
|
|
## 1. CẤU TRÚC MODULE VÀ TỆP NGUỒN
|
|
|
|
### Cấu Trúc Thư Mục
|
|
```
|
|
apps/api/src/modules/mcp/
|
|
├── index.ts
|
|
├── mcp.module.ts
|
|
└── presentation/
|
|
├── mcp-transport.controller.ts
|
|
└── __tests__/
|
|
└── mcp-transport.controller.spec.ts
|
|
```
|
|
|
|
### Tất Cả Tệp Nguồn (4 tệp)
|
|
|
|
#### 1. **apps/api/src/modules/mcp/index.ts**
|
|
- **Loại**: Điểm vào module (xuất khẩu)
|
|
- **Số dòng**: 1
|
|
- **Mục đích**: Xuất khẩu McpIntegrationModule
|
|
- **Xuất khẩu**: `{ McpIntegrationModule }`
|
|
|
|
#### 2. **apps/api/src/modules/mcp/mcp.module.ts**
|
|
- **Loại**: Cấu hình Module NestJS (22 dòng)
|
|
- **Lớp chính**: `McpIntegrationModule implements OnModuleInit`
|
|
- **Trách nhiệm**:
|
|
- Thiết lập module MCP cốt lõi với cấu hình
|
|
- Khởi tạo TypesenseClient cho registry MCP
|
|
- Ghi nhật ký tên máy chủ đã khởi tạo khi module khởi động
|
|
- **Các phụ thuộc được tiêm**:
|
|
- `TypesenseClientService` (từ SearchModule)
|
|
- `McpRegistryService` (từ @goodgo/mcp-servers)
|
|
- `LoggerService` (từ SharedModule)
|
|
- **Nhập khẩu**: SearchModule, AuthModule, McpCoreModule.forRoot()
|
|
- **Controllers**: McpTransportController
|
|
- **Vòng đời**: Triển khai `onModuleInit()`
|
|
|
|
#### 3. **apps/api/src/modules/mcp/presentation/mcp-transport.controller.ts**
|
|
- **Loại**: Controller NestJS (102 dòng)
|
|
- **Lớp chính**: `McpTransportController`
|
|
- **Trách nhiệm**: Lớp truyền tải HTTP cho các kết nối SSE của MCP
|
|
- **Decorator**: @ApiTags, @ApiBearerAuth, @Controller, @UseGuards(JwtAuthGuard)
|
|
- **Thuộc tính**: `transports: Map<string, SSEServerTransport>` (quản lý phiên)
|
|
- **Được tiêm**: `registry: McpRegistryService`
|
|
|
|
**Các endpoint:**
|
|
1. **GET /mcp/servers** - Liệt kê các máy chủ MCP khả dụng (Throttle: 30/60 giây)
|
|
2. **GET /mcp/:serverName/sse** - Mở kết nối SSE (Throttle: 5/60 giây, giới hạn chặt hơn)
|
|
3. **POST /mcp/:serverName/messages** - Gửi tin nhắn tới phiên (Throttle: 30/60 giây)
|
|
|
|
#### 4. **apps/api/src/modules/mcp/presentation/__tests__/mcp-transport.controller.spec.ts**
|
|
- **Loại**: Bộ kiểm thử đơn vị (174 dòng)
|
|
- **Framework**: Vitest
|
|
- **Kiểm thử**: 11 tổng cộng trong 4 khối describe
|
|
- **Phạm vi bao phủ**: Decorator bảo mật, listServers, handleSse, handleMessage
|
|
|
|
## 2. TÓM TẮT CÁC TỆP KIỂM THỬ
|
|
|
|
### Tổng cộng: 1 tệp kiểm thử (174 dòng)
|
|
|
|
**Tệp**: `mcp-transport.controller.spec.ts`
|
|
- **Bộ kiểm thử**: 4 khối describe
|
|
- **Tổng số kiểm thử**: 11
|
|
- **Trạng thái**: ✅ Được kiểm thử đầy đủ
|
|
- **Phạm vi bao phủ**: Các endpoint controller, bảo mật, xử lý lỗi
|
|
|
|
## 3. CẤU TRÚC LỚP DDD
|
|
|
|
**Trạng thái hiện tại**: ĐƠN GIẢN HÓA (chỉ có lớp Presentation)
|
|
|
|
### ✅ Những gì TỒN TẠI:
|
|
- **Lớp Presentation**
|
|
- `presentation/mcp-transport.controller.ts` (102 dòng)
|
|
- `presentation/__tests__/mcp-transport.controller.spec.ts` (174 dòng)
|
|
|
|
### ❌ Những gì KHÔNG TỒN TẠI:
|
|
- **Lớp Domain** - Không có entity, value object, event
|
|
- **Lớp Application** - Không có handler, command, query
|
|
- **Lớp Infrastructure** - Không có repository, adapter
|
|
|
|
### Ghi chú kiến trúc:
|
|
- Hoạt động như lớp bọc tích hợp cho @goodgo/mcp-servers
|
|
- Cầu nối HTTP-to-SSE đơn giản
|
|
- Theo dõi phiên trong bộ nhớ thông qua Map
|
|
- Không có logic nghiệp vụ hay lưu trữ dữ liệu
|
|
|
|
## 4. CÁC LỚP/HANDLER CHÍNH
|
|
|
|
### McpIntegrationModule
|
|
- **Trạng thái**: ⚠️ Được kiểm thử một phần
|
|
- **Phương thức**: constructor, onModuleInit()
|
|
- **Kiểm thử cần thêm**: Khởi tạo module, tích hợp service
|
|
|
|
### McpTransportController
|
|
- **Trạng thái**: ✅ Được kiểm thử đầy đủ
|
|
- **Phương thức**: listServers(), handleSse(), handleMessage()
|
|
- **Kiểm thử**: 11 bài kiểm thử toàn diện bao phủ tất cả phương thức
|
|
|
|
## 5. MẪU KIỂM THỬ TỪ CÁC MODULE KHÁC
|
|
|
|
### Mẫu 1: Module Auth (Handler đơn giản)
|
|
```typescript
|
|
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);
|
|
});
|
|
});
|
|
```
|
|
|
|
### Mẫu 2: Module Payments (Handler phức tạp)
|
|
```typescript
|
|
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);
|
|
});
|
|
});
|
|
```
|
|
|
|
### Mẫu 3: Kiểm thử Domain Entity
|
|
```typescript
|
|
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);
|
|
});
|
|
});
|
|
```
|
|
|
|
### Mẫu 4: Kiểm thử Service Infrastructure
|
|
```typescript
|
|
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. TÓM TẮT QUY ƯỚC KIỂM THỬ
|
|
|
|
### Framework và Thiết lập
|
|
- **Framework**: Vitest
|
|
- **Môi trường**: Node.js
|
|
- **Globals**: Được bật
|
|
- **Mẫu tệp**: `*.spec.ts`
|
|
- **Tổ chức kiểm thử**: Thư mục con `__tests__/`
|
|
|
|
### Mẫu Mock
|
|
1. **Service Mock**: `mockService = { method: vi.fn().mockResolvedValue(value) }`
|
|
2. **Module Mock**: `vi.mock('@goodgo/mcp-servers', () => ({ ... }))`
|
|
3. **Configuration Mock**: `get: vi.fn((key) => env[key])`
|
|
|
|
### Cấu Trúc Kiểm Thử
|
|
```typescript
|
|
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);
|
|
});
|
|
});
|
|
});
|
|
```
|
|
|
|
### Lệnh Kiểm Thử
|
|
```bash
|
|
# Chạy kiểm thử MCP
|
|
pnpm test -- src/modules/mcp
|
|
|
|
# Chế độ theo dõi
|
|
pnpm test -- --watch src/modules/mcp
|
|
|
|
# Với độ bao phủ
|
|
pnpm test -- --coverage src/modules/mcp
|
|
```
|
|
|
|
## 7. KHUYẾN NGHỊ
|
|
|
|
### Tức thì
|
|
- ✅ Duy trì độ bao phủ kiểm thử controller
|
|
- 📝 Thêm kiểm thử cho McpIntegrationModule.onModuleInit()
|
|
- 📝 Kiểm thử tiêm phụ thuộc module
|
|
|
|
### Tương lai
|
|
- 🏗️ Thêm kiểm thử tích hợp cho vòng đời SSE đầy đủ
|
|
- 🏗️ Nếu thêm logic domain, tuân theo mẫu module payments
|
|
- 🏗️ Nếu thêm handler, sử dụng mẫu CQRS từ các module auth/payments
|
|
|