Normalize MCP response structures across all tools

Implement changes from MCP_NORMALIZATION_FIX.md to provide consistent
response structure across all MCP tools. This fixes the bot integration
issue where different tools returned data in different structures.

Changes:
- get_valuation_comparables:
  - Rename "comparables" → "deals"
  - Move "total_comparables" → "market_statistics.deal_breakdown.total_deals"
  - Add "search_parameters" section with "filters_applied"
  - Move "statistics" → "market_statistics"

- find_recent_deals_for_address:
  - Rename "price_stats.average_price" → "price_statistics.mean"
  - Rename "price_stats.median_price" → "price_statistics.median"
  - Rename "area_stats" → "area_statistics"
  - Rename "price_per_sqm_stats" → "price_per_sqm_statistics"

- get_deal_statistics:
  - Add "search_parameters" section
  - Move "statistics" → "market_statistics"
  - Add "market_statistics.deal_breakdown.total_deals"

- analyze_market_trends:
  - Add "market_statistics.deal_breakdown.total_deals"
  - Keep existing tool-specific fields (yearly_trends, etc.)

- get_market_activity_metrics:
  - Add "market_statistics.deal_breakdown.total_deals"
  - Keep existing tool-specific metrics

All tools now follow standard structure:
{
  "search_parameters" or "analysis_parameters": {...},
  "market_statistics": {
    "deal_breakdown": {"total_deals": N},
    "price_statistics": {"mean": ..., "median": ...},
    "area_statistics": {...},
    "price_per_sqm_statistics": {...}
  },
  "deals": [...]
}

Updated tests to match new normalized structure.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Nitzan P
2025-11-23 09:49:52 +02:00
parent c444e88a10
commit e791d3c1ed
4 changed files with 476 additions and 76 deletions
+15 -8
View File
@@ -364,10 +364,13 @@ class TestGetValuationComparables:
)
parsed = json.loads(result)
assert "filters_applied" in parsed
assert "statistics" in parsed
assert "comparables" in parsed
assert parsed["filters_applied"]["property_type"] == "דירה"
# Normalized structure: filters_applied is now in search_parameters
assert "search_parameters" in parsed
assert "filters_applied" in parsed["search_parameters"]
assert parsed["search_parameters"]["filters_applied"]["property_type"] == "דירה"
# Normalized structure: comparables -> deals
assert "deals" in parsed
assert "market_statistics" in parsed
@patch("nadlan_mcp.fastmcp_server.client")
def test_comparables_strips_bloat(self, mock_client):
@@ -392,7 +395,8 @@ class TestGetValuationComparables:
result = fastmcp_server.get_valuation_comparables("test address")
parsed = json.loads(result)
comparable = parsed["comparables"][0]
# Normalized structure: comparables -> deals
comparable = parsed["deals"][0]
assert "shape" not in comparable
assert "sourceorder" not in comparable
# source_polygon_id is kept when added by processing
@@ -421,9 +425,12 @@ class TestGetDealStatistics:
result = fastmcp_server.get_deal_statistics("test address")
parsed = json.loads(result)
assert "address" in parsed
assert "statistics" in parsed
assert parsed["statistics"]["total_deals"] == 2 # Field name is total_deals in model
# Normalized structure: address is now in search_parameters, statistics -> market_statistics
assert "search_parameters" in parsed
assert "address" in parsed["search_parameters"]
assert "market_statistics" in parsed
assert "deal_breakdown" in parsed["market_statistics"]
assert parsed["market_statistics"]["deal_breakdown"]["total_deals"] == 2
class TestGetMarketActivityMetrics: