# MCP Servers Documentation GoodGo Platform sử dụng **Model Context Protocol (MCP)** để cấp quyền truy cập các công cụ chuyên dụng cho Claude AI. Ba MCP servers chính cung cấp khả năng **tìm kiếm bất động sản**, **phân tích thị trường**, và **định giá tự động (AVM)**. --- ## Overview | Server | Port | Tools | Purpose | |--------|------|-------|---------| | **Property Search** | 3001 | `search_properties`, `compare_properties`, `get_property_details` | Tìm kiếm bất động sản, so sánh, chi tiết | | **Market Analytics** | 3001 | `get_market_report`, `analyze_trends`, `get_price_indices` | Phân tích thị trường, xu hướng giá | | **Valuation** | 3001 | `estimate_valuation`, `extract_features`, `compare_valuations` | Định giá BĐS, so sánh XGBoost | **Architecture:** - All MCP servers are **in-process** (không tách microservice cho MVP) - Chạy cùng process NestJS API - HTTP transport dùng `/mcp/tools/*` endpoint - Claude API calls `POST /mcp/tools/{toolName}` để invoke tools --- ## 1. Property Search Server ### Purpose Cung cấp công cụ tìm kiếm bất động sản với: - Full-text search (Typesense) - Geo-spatial search (PostGIS) - Faceted filtering (giá, loại, phòng ngủ, quận huyện) ### Tools #### `search_properties` Tìm kiếm bất động sản với nhiều tiêu chí. **Input Schema:** ```json { "query": "chung cư quận 1", "filters": { "priceMin": 1000000000, "priceMax": 5000000000, "bedrooms": 2, "district": "Quận 1", "propertyType": "APARTMENT" }, "sort": "price_asc", "limit": 10, "offset": 0 } ``` **Parameters:** | Param | Type | Required | Default | Notes | |-------|------|----------|---------|-------| | `query` | string | Yes | - | Tìm kiếm từ khóa (tiêu đề, mô tả) | | `filters.priceMin` | number | No | 0 | Giá tối thiểu (VND) | | `filters.priceMax` | number | No | ∞ | Giá tối đa (VND) | | `filters.bedrooms` | number | No | - | Số phòng ngủ | | `filters.district` | string | No | - | Quận huyện | | `filters.propertyType` | enum | No | - | APARTMENT, HOUSE, LAND, ROOM_RENTAL | | `sort` | enum | No | `relevance` | `price_asc`, `price_desc`, `newest`, `relevance` | | `limit` | number | No | 20 | Số kết quả (1-100) | | `offset` | number | No | 0 | Phân trang offset | **Output Example:** ```json { "total": 245, "results": [ { "id": "prop-001", "title": "Căn hộ 2PN view sông Sài Gòn", "type": "APARTMENT", "price": 3500000000, "bedrooms": 2, "bathrooms": 2, "area": 85, "district": "Quận 1", "ward": "Phường Bến Nghé", "address": "123 Tôn Đức Thắng, Q.1", "agentName": "Nguyễn Văn A", "agentPhone": "0987654321", "status": "ACTIVE", "createdAt": "2026-04-20T10:30:00Z" } ], "facets": { "districts": [ { "name": "Quận 1", "count": 42 }, { "name": "Quận 3", "count": 38 } ], "propertyTypes": [ { "name": "APARTMENT", "count": 120 }, { "name": "HOUSE", "count": 85 } ] } } ``` --- #### `compare_properties` So sánh 2-5 bất động sản dựa trên giá, diện tích, vị trí, etc. **Input Schema:** ```json { "propertyIds": ["prop-001", "prop-002", "prop-003"], "metrics": ["price", "area", "price_per_sqm", "location_score", "agent_rating"] } ``` **Output Example:** ```json { "comparison": [ { "propertyId": "prop-001", "title": "Căn hộ 2PN Q.1", "price": 3500000000, "area": 85, "price_per_sqm": 41176470, "location_score": 4.8, "agent_rating": 4.5 }, { "propertyId": "prop-002", "title": "Căn hộ 2PN Q.3", "price": 2800000000, "area": 78, "price_per_sqm": 35897436, "location_score": 4.3, "agent_rating": 4.2 } ], "recommendation": "prop-002 có giá tốt hơn với vị trí tương đương" } ``` --- #### `get_property_details` Lấy chi tiết đầy đủ của một bất động sản. **Input Schema:** ```json { "propertyId": "prop-001" } ``` **Output Example:** ```json { "id": "prop-001", "title": "Căn hộ 2PN view sông Sài Gòn", "description": "Căn hộ cao cấp tại trung tâm Q.1...", "type": "APARTMENT", "price": 3500000000, "bedrooms": 2, "bathrooms": 2, "area": 85, "district": "Quận 1", "ward": "Phường Bến Nghé", "address": "123 Tôn Đức Thắng, Q.1", "coordinates": { "latitude": 10.7769, "longitude": 106.7009 }, "features": ["view sông", "ban công rộng", "tầng cao", "gần metro"], "agent": { "id": "agent-001", "name": "Nguyễn Văn A", "phone": "0987654321", "rating": 4.5, "reviews": 47 }, "media": [ { "type": "image", "url": "https://storage.goodgo.app/prop-001/img-1.jpg" } ], "status": "ACTIVE", "createdAt": "2026-04-20T10:30:00Z", "reviews": [ { "author": "Trần Văn B", "rating": 5, "text": "Căn hộ đẹp, vị trí tuyệt vời" } ] } ``` --- ## 2. Market Analytics Server ### Purpose Cung cấp dữ liệu thị trường bất động sản: - Báo cáo giá theo quận huyện - Phân tích xu hướng giá theo thời gian - Chỉ số thị trường ### Tools #### `get_market_report` Lấy báo cáo thị trường theo quận huyện. **Input Schema:** ```json { "district": "Quận 1", "propertyType": "APARTMENT", "period": "monthly" } ``` **Output Example:** ```json { "district": "Quận 1", "propertyType": "APARTMENT", "period": "April 2026", "statistics": { "averagePrice": 3200000000, "medianPrice": 3100000000, "priceMin": 800000000, "priceMax": 8500000000, "averageArea": 82, "averagePricePerSqm": 39024390, "activeListings": 342, "soldListings": 28, "rentedListings": 15 }, "trends": { "priceChangePercent": 2.5, "priceChangeVsLastMonth": "Tăng 2.5%", "velocityDays": 15 } } ``` --- #### `analyze_trends` Phân tích xu hướng giá theo thời gian. **Input Schema:** ```json { "district": "Quận 1", "propertyType": "APARTMENT", "months": 12 } ``` **Output Example:** ```json { "district": "Quận 1", "propertyType": "APARTMENT", "trend": [ { "month": "May 2025", "averagePrice": 2900000000, "medianPrice": 2800000000, "activeListings": 250 }, { "month": "April 2026", "averagePrice": 3200000000, "medianPrice": 3100000000, "activeListings": 342 } ], "forecast": { "nextMonthPredicted": 3280000000, "confidence": 0.75, "direction": "up" } } ``` --- #### `get_price_indices` Lấy chỉ số giá toàn thị trường (bình thường hóa = 100). **Input Schema:** ```json { "baseMonth": "January 2025" } ``` **Output Example:** ```json { "baseIndex": 100, "baseMonth": "January 2025", "indices": [ { "month": "January 2025", "indexValue": 100, "growth": 0 }, { "month": "April 2026", "indexValue": 110.5, "growth": 10.5 } ], "byDistrict": { "Quận 1": 112.3, "Quận 3": 108.7, "Thủ Đức": 105.2 } } ``` --- ## 3. Valuation Server ### Purpose Định giá tự động bất động sản dùng mô hình **XGBoost**: - Estimate valuation based on features - Extract features from description - Compare valuations across similar properties ### Tools #### `estimate_valuation` Ước lượng giá bất động sản dựa trên đặc trưng. **Input Schema:** ```json { "district": "Quận 1", "propertyType": "APARTMENT", "area": 85, "bedrooms": 2, "bathrooms": 2, "features": ["view sông", "ban công", "tầng cao", "gần metro"], "yearBuilt": 2015, "location": { "latitude": 10.7769, "longitude": 106.7009 } } ``` **Output Example:** ```json { "estimatedPrice": 3250000000, "priceRange": { "low": 2850000000, "high": 3650000000 }, "confidence": 0.82, "factors": { "area": "Positive (85 sqm)", "location": "High demand (Q.1)", "features": "Premium (view sông, gần metro)", "yearBuilt": "Neutral (11 years old)" }, "comparables": [ { "id": "prop-001", "actualPrice": 3200000000, "similarity": 0.89 } ] } ``` --- #### `extract_features` Trích xuất đặc trưng từ mô tả bất động sản (NLP). **Input Schema:** ```json { "description": "Căn hộ cao cấp 2 phòng ngủ, 2 phòng tắm, view sông Sài Gòn, ban công rộng, gần trạm metro, tầng 15, xây năm 2015...", "title": "Căn hộ 2PN view sông Sài Gòn" } ``` **Output Example:** ```json { "extracted": { "bedrooms": 2, "bathrooms": 2, "area": null, "features": ["view sông", "ban công", "gần metro", "tầng cao"], "yearBuilt": 2015, "condition": "tốt" }, "confidence": { "bedrooms": 0.98, "features": 0.85, "yearBuilt": 0.92 }, "uncertainties": [ "area not mentioned", "exact floor number not in description" ] } ``` --- #### `compare_valuations` So sánh định giá của các bất động sản tương tự. **Input Schema:** ```json { "referencePropertyId": "prop-001", "candidatePropertyIds": ["prop-002", "prop-003", "prop-004"] } ``` **Output Example:** ```json { "reference": { "propertyId": "prop-001", "title": "Căn hộ 2PN Q.1", "actualPrice": 3500000000, "estimatedPrice": 3250000000 }, "candidates": [ { "propertyId": "prop-002", "title": "Căn hộ 2PN Q.3", "actualPrice": 2800000000, "estimatedPrice": 2950000000, "overUndervalued": "Undervalued by 5.1%", "similarity": 0.76 } ], "recommendation": "prop-002 is a good value compared to reference property" } ``` --- ## Implementation Details ### File Structure ``` apps/api/src/ ├── modules/ │ └── mcp/ │ ├── mcp.module.ts # Module definition │ ├── mcp.controller.ts # HTTP endpoint: POST /mcp/tools/:toolName │ ├── mcp-registry.service.ts # Registry: tool name → handler function │ ├── servers/ │ │ ├── property-search.server.ts │ │ ├── market-analytics.server.ts │ │ └── valuation.server.ts │ └── dto/ │ ├── search-properties.dto.ts │ ├── market-report.dto.ts │ └── estimate-valuation.dto.ts ``` ### McpRegistryService ```typescript // Register tools export class McpRegistryService { private tools = new Map(); register(name: string, tool: Tool) { this.tools.set(name, tool); } invoke(name: string, input: any): Promise { const tool = this.tools.get(name); if (!tool) throw new NotFoundException(`Tool ${name} not found`); return tool.execute(input); } } ``` ### HTTP Endpoint ```typescript @Post('/mcp/tools/:toolName') @Auth() // JWT required async invokeTool( @Param('toolName') toolName: string, @Body() input: any ) { return this.mcpRegistry.invoke(toolName, input); } ``` ### Tool Pattern ```typescript interface Tool { name: string; schema: JsonSchema; // Input validation execute(input: any): Promise; } class SearchPropertiesTool implements Tool { name = 'search_properties'; schema = { /* JSON Schema */ }; execute(input: SearchPropertiesInput): Promise { // Implementation } } ``` --- ## Error Handling All MCP tools return consistent error format: ```json { "error": { "code": "INVALID_INPUT", "message": "District 'Quận XYZ' not found", "details": { "field": "district", "value": "Quận XYZ" } } } ``` --- ## Performance Considerations ### Caching - Market Analytics: Cache reports for 1 hour - Property Search: Cache facets, invalidate on new listing - Valuation: Cache model predictions for 24 hours ### Rate Limiting - Default: 100 req/minute per user - MCP tools: 50 req/minute per tool (stricter) - Burst: 10 req/second --- ## Testing ### Unit Tests ```bash pnpm test -- mcp/servers ``` ### Integration Tests ```bash # Test via HTTP curl -X POST http://localhost:3001/mcp/tools/search_properties \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"query": "chung cu quan 1", "limit": 5}' ``` --- ## References - MCP Specification: https://modelcontextprotocol.io/ - Claude API: https://anthropic.com/api - Implementation: `apps/api/src/modules/mcp/`