Files
goodgo-platform/docs/mcp-servers.md
Ho Ngoc Hai e798468e4c docs(GOO-33): comprehensive documentation sprint
Create/update all Sprint 6 documentation:
- CHANGELOG.md: document GOO-33 and recent audit findings
- CONTRIBUTING.md: add branching, PR, commit conventions
- docs/ci-cd.md: GitHub Actions pipeline documentation
- docs/onboarding.md: developer setup & onboarding guide
- docs/mcp-servers.md: MCP servers API documentation
- docs/PROJECT_TRACKER.md: mark GOO-33 as in_progress
- docs/QA_TRACKER.md: test status and verification plans

Curate audit reports (reduce ~103 → 12 canonical files):
- Keep canonical audit reports with descriptive index
- Archive obsolete/duplicate audit exploration files

Acceptance Criteria:
- [x] QA_TRACKER.md exists with current test status
- [x] CHANGELOG.md updated to today
- [x] PROJECT_TRACKER.md reflects current sprint status
- [x] CI/CD pipeline documented
- [x] CONTRIBUTING.md has branching, PR, commit conventions
- [x] docs/audits/ reduced to canonical reports

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-22 23:29:20 +07:00

12 KiB

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:

{
  "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:

{
  "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:

{
  "propertyIds": ["prop-001", "prop-002", "prop-003"],
  "metrics": ["price", "area", "price_per_sqm", "location_score", "agent_rating"]
}

Output Example:

{
  "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:

{
  "propertyId": "prop-001"
}

Output Example:

{
  "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:

{
  "district": "Quận 1",
  "propertyType": "APARTMENT",
  "period": "monthly"
}

Output Example:

{
  "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
  }
}

Phân tích xu hướng giá theo thời gian.

Input Schema:

{
  "district": "Quận 1",
  "propertyType": "APARTMENT",
  "months": 12
}

Output Example:

{
  "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:

{
  "baseMonth": "January 2025"
}

Output Example:

{
  "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:

{
  "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:

{
  "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:

{
  "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:

{
  "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:

{
  "referencePropertyId": "prop-001",
  "candidatePropertyIds": ["prop-002", "prop-003", "prop-004"]
}

Output Example:

{
  "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

// Register tools
export class McpRegistryService {
  private tools = new Map<string, Tool>();

  register(name: string, tool: Tool) {
    this.tools.set(name, tool);
  }

  invoke(name: string, input: any): Promise<any> {
    const tool = this.tools.get(name);
    if (!tool) throw new NotFoundException(`Tool ${name} not found`);
    return tool.execute(input);
  }
}

HTTP Endpoint

@Post('/mcp/tools/:toolName')
@Auth()  // JWT required
async invokeTool(
  @Param('toolName') toolName: string,
  @Body() input: any
) {
  return this.mcpRegistry.invoke(toolName, input);
}

Tool Pattern

interface Tool {
  name: string;
  schema: JsonSchema;  // Input validation
  execute(input: any): Promise<any>;
}

class SearchPropertiesTool implements Tool {
  name = 'search_properties';
  schema = { /* JSON Schema */ };

  execute(input: SearchPropertiesInput): Promise<any> {
    // Implementation
  }
}

Error Handling

All MCP tools return consistent error format:

{
  "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

pnpm test -- mcp/servers

Integration Tests

# 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