Continue phase 6

This commit is contained in:
Nitzan Pomerantz
2025-10-31 18:41:48 +02:00
parent 739d4f8578
commit 280b0c9b1c
6 changed files with 1492 additions and 80 deletions
+636
View File
@@ -0,0 +1,636 @@
# API Reference
Complete reference for Nadlan-MCP's MCP tools and Python library.
## Table of Contents
- [MCP Tools](#mcp-tools) - For AI agents (Claude, etc.)
- [Python Client](#python-client) - For direct library usage
- [Data Models](#data-models) - Pydantic models reference
- [Configuration](#configuration) - Environment variables and settings
---
## MCP Tools
These tools are available when running Nadlan-MCP as an MCP server.
### Core Tools
#### `autocomplete_address`
Search and validate Israeli addresses.
**Parameters:**
- `search_text` (string, required): Address to search (Hebrew or English)
**Returns:** JSON with matching addresses and coordinates
**Example:**
```json
{
"search_text": "רוטשילד תל אביב"
}
```
---
#### `find_recent_deals_for_address`
Find all recent real estate deals for a specific address.
**Parameters:**
- `address` (string, required): Address to search
- `years_back` (int, default: 2): Number of years to look back
- `radius_meters` (int, default: 30): Search radius in meters
- `max_deals` (int, default: 100): Maximum deals to return
- `deal_type` (int, default: 2): Deal type (1=new construction, 2=resale)
**Returns:** JSON with deals, sorted by priority and date
**Example:**
```json
{
"address": "רוטשילד 1 תל אביב",
"years_back": 2,
"radius_meters": 50
}
```
---
#### `get_deals_by_radius`
Get polygon metadata within a radius of coordinates.
**Parameters:**
- `latitude` (float, required): Latitude coordinate
- `longitude` (float, required): Longitude coordinate
- `radius_meters` (int, default: 500): Search radius in meters
**Returns:** JSON with polygon metadata (NOT individual deals)
**Note:** This returns **polygon metadata**, not deals. Use `get_street_deals` or `find_recent_deals_for_address` for actual deals.
---
#### `get_street_deals`
Get deals for a specific street polygon.
**Parameters:**
- `polygon_id` (string, required): Street polygon ID
- `limit` (int, default: 100): Maximum deals to return
- `deal_type` (int, default: 2): Deal type filter
**Returns:** JSON with street-level deals
---
#### `get_neighborhood_deals`
Get deals for a neighborhood polygon.
**Parameters:**
- `polygon_id` (string, required): Neighborhood polygon ID
- `limit` (int, default: 100): Maximum deals to return
- `deal_type` (int, default: 2): Deal type filter
**Returns:** JSON with neighborhood-level deals
---
### Analysis Tools
#### `analyze_market_trends`
Analyze market trends and price patterns for an area.
**Parameters:**
- `address` (string, required): Address to analyze
- `years_back` (int, default: 3): Years of data to analyze
- `radius_meters` (int, default: 100): Search radius
- `max_deals` (int, default: 100): Maximum deals to analyze
- `deal_type` (int, default: 2): Deal type filter
**Returns:** JSON with:
- Deal statistics (prices, price/m², trends)
- Time-series analysis
- Market summary
**Example:**
```json
{
"address": "דיזנגוף 50 תל אביב",
"years_back": 3
}
```
---
#### `compare_addresses`
Compare real estate markets between multiple addresses.
**Parameters:**
- `addresses` (array of strings, required): List of addresses to compare
**Returns:** JSON with comparative analysis
**Example:**
```json
{
"addresses": [
"רוטשילד 1 תל אביב",
"דיזנגוף 50 תל אביב",
"ז'בוטינסקי 1 רמת גן"
]
}
```
---
### Valuation Tools
#### `get_valuation_comparables`
Get comparable properties for valuation analysis.
**Parameters:**
- `address` (string, required): Address to find comparables for
- `years_back` (int, default: 2): Years to look back
- `property_type` (string, optional): Filter by property type (e.g., "דירה")
- `min_rooms` (float, optional): Minimum rooms
- `max_rooms` (float, optional): Maximum rooms
- `min_price` (float, optional): Minimum price (NIS)
- `max_price` (float, optional): Maximum price (NIS)
- `min_area` (float, optional): Minimum area (m²)
- `max_area` (float, optional): Maximum area (m²)
- `min_floor` (int, optional): Minimum floor
- `max_floor` (int, optional): Maximum floor
- `radius_meters` (int, default: 100): Search radius
- `max_comparables` (int, default: 50): Max comparables to return
**Returns:** JSON with filtered comparable deals and statistics
**Example:**
```json
{
"address": "רוטשילד 10 תל אביב",
"min_rooms": 3,
"max_rooms": 4,
"min_area": 70,
"max_area": 100
}
```
---
#### `get_deal_statistics`
Calculate statistical aggregations on deal data.
**Parameters:**
- `address` (string, required): Address to analyze
- `years_back` (int, default: 2): Years to analyze
- `property_type` (string, optional): Filter by property type
- `min_rooms` (float, optional): Minimum rooms
- `max_rooms` (float, optional): Maximum rooms
**Returns:** JSON with statistics (mean, median, percentiles, std dev)
---
#### `get_market_activity_metrics`
Get comprehensive market activity and investment analysis.
**Parameters:**
- `address` (string, required): Address to analyze
- `years_back` (int, default: 2): Years to analyze
- `radius_meters` (int, default: 100): Search radius
**Returns:** JSON with:
- Market activity score and trends
- Market liquidity metrics
- Investment potential analysis
- Price appreciation and volatility
---
## Python Client
For direct Python usage without MCP.
### Installation
```python
from nadlan_mcp.govmap import GovmapClient
client = GovmapClient()
```
### Main Methods
#### `autocomplete_address()`
```python
def autocomplete_address(search_text: str) -> AutocompleteResponse:
"""
Search for addresses using autocomplete.
Args:
search_text: Address to search (Hebrew or English)
Returns:
AutocompleteResponse with matching addresses
Raises:
ValueError: If search text is invalid
requests.RequestException: On API errors
"""
```
**Example:**
```python
result = client.autocomplete_address("רוטשילד תל אביב")
for address in result.results:
print(f"{address.text} - {address.coordinates}")
```
---
#### `find_recent_deals_for_address()`
```python
def find_recent_deals_for_address(
address: str,
years_back: int = 2,
radius: int = 50,
max_deals: int = 100,
deal_type: int = 2
) -> List[Deal]:
"""
Find all relevant deals for an address.
Args:
address: Address to search
years_back: Years to look back (default: 2)
radius: Search radius in meters (default: 50)
max_deals: Maximum deals to return (default: 100)
deal_type: 1=new construction, 2=resale (default: 2)
Returns:
List of Deal models, sorted by priority and date
Raises:
ValueError: If address invalid or no results found
"""
```
**Example:**
```python
deals = client.find_recent_deals_for_address(
"רוטשילד 1 תל אביב",
years_back=3,
radius=100
)
for deal in deals[:5]:
print(f"{deal.address_description}: ₪{deal.deal_amount:,.0f}")
```
---
#### `filter_deals_by_criteria()`
```python
def filter_deals_by_criteria(
deals: List[Deal],
property_type: Optional[str] = None,
min_rooms: Optional[float] = None,
max_rooms: Optional[float] = None,
min_price: Optional[float] = None,
max_price: Optional[float] = None,
min_area: Optional[float] = None,
max_area: Optional[float] = None,
min_floor: Optional[int] = None,
max_floor: Optional[int] = None,
) -> List[Deal]:
"""
Filter deals by various criteria.
Args:
deals: List of Deal models to filter
property_type: Property type (Hebrew, e.g., "דירה")
min_rooms/max_rooms: Room count range
min_price/max_price: Price range (NIS)
min_area/max_area: Area range (m²)
min_floor/max_floor: Floor range
Returns:
Filtered list of Deal models
Raises:
ValueError: If filter ranges are invalid
"""
```
**Example:**
```python
filtered = client.filter_deals_by_criteria(
deals,
property_type="דירה",
min_rooms=3,
max_rooms=4,
min_price=1000000,
max_price=2000000
)
```
---
#### `calculate_deal_statistics()`
```python
def calculate_deal_statistics(deals: List[Deal]) -> DealStatistics:
"""
Calculate statistical aggregations.
Args:
deals: List of Deal models
Returns:
DealStatistics model with mean, median, percentiles, etc.
Raises:
ValueError: If deals list is empty
"""
```
---
#### `calculate_market_activity_score()`
```python
def calculate_market_activity_score(
deals: List[Deal],
time_period_months: Optional[int] = None
) -> MarketActivityScore:
"""
Calculate market activity metrics.
Args:
deals: List of Deal models
time_period_months: Time period to analyze (None = all data)
Returns:
MarketActivityScore model
Raises:
ValueError: If deals list is empty
"""
```
---
#### `get_market_liquidity()`
```python
def get_market_liquidity(
deals: List[Deal],
time_period_months: Optional[int] = None
) -> LiquidityMetrics:
"""
Calculate market liquidity metrics.
Args:
deals: List of Deal models
time_period_months: Time period to analyze
Returns:
LiquidityMetrics model
Raises:
ValueError: If deals list is empty
"""
```
---
#### `analyze_investment_potential()`
```python
def analyze_investment_potential(deals: List[Deal]) -> InvestmentAnalysis:
"""
Analyze investment potential of an area.
Args:
deals: List of Deal models
Returns:
InvestmentAnalysis model
Raises:
ValueError: If deals list is empty or insufficient data
"""
```
---
## Data Models
All models are Pydantic v2 models with validation.
### Deal
Primary model for real estate transaction data.
```python
class Deal(BaseModel):
objectid: int
deal_amount: Optional[float]
deal_date: date | str
property_type_description: Optional[str]
rooms: Optional[float]
asset_area: Optional[float]
floor_number: Optional[int]
floor: Optional[str]
address_description: Optional[str]
# Computed field
@computed_field
@property
def price_per_sqm(self) -> Optional[float]:
"""Calculate price per square meter."""
if self.deal_amount and self.asset_area and self.asset_area > 0:
return self.deal_amount / self.asset_area
return None
```
### DealStatistics
Statistical aggregations on deal data.
```python
class DealStatistics(BaseModel):
count: int
mean_price: float
median_price: float
min_price: float
max_price: float
std_dev_price: float
percentile_25_price: float
percentile_75_price: float
mean_price_per_sqm: Optional[float]
median_price_per_sqm: Optional[float]
# ... more fields
```
### MarketActivityScore
Market activity metrics.
```python
class MarketActivityScore(BaseModel):
activity_score: float # 0-100
activity_level: str # very_high, high, moderate, low, very_low
trend: str # improving, stable, declining
deals_per_month: float
unique_months: int
total_deals: int
```
### InvestmentAnalysis
Investment potential analysis.
```python
class InvestmentAnalysis(BaseModel):
investment_score: float # 0-100
price_trend: str
price_appreciation_rate: float # % per year
market_stability: str
volatility_score: float
recommendation: str
```
### LiquidityMetrics
Market liquidity analysis.
```python
class LiquidityMetrics(BaseModel):
liquidity_score: float # 0-100
total_deals: int
avg_deals_per_month: float
deal_velocity: float
market_activity_level: str
trend_direction: str
```
---
## Configuration
### Environment Variables
```bash
# API Settings
GOVMAP_BASE_URL=https://www.govmap.gov.il/api/
GOVMAP_USER_AGENT=NadlanMCP/2.0.0
# Timeouts (seconds)
GOVMAP_CONNECT_TIMEOUT=10
GOVMAP_READ_TIMEOUT=30
# Retry Settings
GOVMAP_MAX_RETRIES=3
GOVMAP_RETRY_MIN_WAIT=1
GOVMAP_RETRY_MAX_WAIT=10
# Rate Limiting
GOVMAP_REQUESTS_PER_SECOND=5.0
# Defaults
GOVMAP_DEFAULT_RADIUS=50
GOVMAP_DEFAULT_YEARS_BACK=2
GOVMAP_DEFAULT_DEAL_LIMIT=100
# Performance
GOVMAP_MAX_POLYGONS=10
```
### Programmatic Configuration
```python
from nadlan_mcp.config import GovmapConfig, set_config
config = GovmapConfig(
connect_timeout=15,
read_timeout=45,
max_retries=5,
requests_per_second=3.0,
max_polygons=5
)
set_config(config)
```
---
## Error Handling
### Common Errors
**ValueError**
- Invalid input parameters
- Empty results
- Invalid filter ranges
**requests.RequestException**
- Network errors
- API timeouts
- HTTP errors
**pydantic.ValidationError**
- Invalid model data (handled internally, logged as warnings)
### Example
```python
from nadlan_mcp.govmap import GovmapClient
client = GovmapClient()
try:
deals = client.find_recent_deals_for_address("invalid")
except ValueError as e:
print(f"Invalid input: {e}")
except requests.RequestException as e:
print(f"API error: {e}")
```
---
## Rate Limiting
Built-in rate limiting respects API limits:
- Default: 5 requests/second
- Configurable via `GOVMAP_REQUESTS_PER_SECOND`
- Automatic retry with exponential backoff
---
## Examples
See `examples/` directory for complete usage examples:
- `basic_search.py` - Simple address lookup
- `market_analysis.py` - Trend analysis
- `investment_analysis.py` - Multi-location comparison
- `valuation.py` - Property valuation
---
For more information, see:
- [README.md](README.md) - Overview and quickstart
- [DEPLOYMENT.md](DEPLOYMENT.md) - Deployment guide
- [CONTRIBUTING.md](CONTRIBUTING.md) - Development guide