chaim 2d49172f80 chore: track .env.example (Task Master template, no secrets)
The .gitignore had three competing rules — .env.* (line 70), *.env.*
(line 259), and a stale negation !.env.example (line 71) that lost to
the later rules. Adding the negation at the end of the file so it wins.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 21:32:38 +00:00
2025-10-30 22:24:40 +02:00
2025-10-31 19:02:21 +02:00
2025-10-31 19:02:33 +02:00
2025-10-30 22:24:40 +02:00
2025-10-30 22:24:40 +02:00
2025-10-31 18:41:48 +02:00
2025-10-30 22:24:40 +02:00
2025-10-31 19:12:52 +02:00
2025-07-12 12:27:22 +03:00
2025-10-26 10:58:46 +02:00
2025-10-30 22:24:40 +02:00
2025-10-30 22:24:40 +02:00
2025-10-31 18:41:48 +02:00
2025-10-30 20:47:02 +02:00
2025-10-30 22:24:40 +02:00

Nadlan-MCP — חיפוש נדל"ן ושמאי מכריע

כלי web ו-MCP חינמי וקוד פתוח לחיפוש מידע נדל"ני בישראל: עסקאות נדל"ן עדכניות מ-Govmap והחלטות שמאי מכריע ממשרד המשפטים — בממשק עברי מלא עם תמיכת RTL.

TL;DR: הכנס כתובת, גוש+חלקה או שם של שמאי מכריע — מקבל בו-זמנית עסקאות באזור והחלטות שומה רלוונטיות, כולל הורדת PDF.


תוכן עניינים


מה הכלי עושה

הכלי מחבר בין שני מקורות מידע ממשלתיים שלא היו זמינים יחד עד היום:

מקור מה מספק תדירות עדכון
Govmap (www.govmap.gov.il) עסקאות נדל"ן רשומות מ-2010 ואילך — מחיר, שטח, חדרים, קומה, גוש/חלקה/תת-חלקה חודשי
משרד המשפטים (pub-justice.openapi.gov.il) החלטות שמאי מכריע — שומות הכרעה, ערעורים, היטלי השבחה, פיצויי הפקעה, וכד' שוטף

המידע מוצג בטבלה אחת, מסונכרן בין המקורות לפי גוש/חלקה, עם קישורים ישירים ל-PDF של ההחלטות.


שני ממשקים — Web ו-MCP

1. ממשק Web (React)

ממשק משתמש מלא לבני אדם:

https://nadlan-mcp.dev.marcus-law.co.il

טופס חיפוש, שתי טבלאות (עסקאות + שומות), פתיחה והורדה של PDF, RTL מלא.

2. ממשק MCP (Model Context Protocol)

שרת MCP ל-LLMs ול-AI agents — מאפשר ל-Claude / ChatGPT / כל סוכן AI לחפש בעצמו מידע נדל"ני. נחשף ב-/mcp כ-streamable HTTP. כולל 10 כלים:

  • autocomplete_address — חיפוש כתובת
  • find_recent_deals_for_address — עסקאות סביב כתובת
  • analyze_market_trends — ניתוח מגמות מחירים
  • compare_addresses — השוואה בין שתי כתובות
  • get_valuation_comparables — השוואות שמאיות
  • get_deal_statistics — סטטיסטיקה מצרפית
  • get_market_activity_metrics — מדדי פעילות שוק
  • ועוד.

ראה nadlan_mcp/fastmcp_server.py.


תכונות עיקריות

🔍 שלושה אופני חיפוש בו-זמנית

חיפוש לפי כתובת (קטלב 5 צור הדסה), לפי גוש+חלקה (גוש 6212 חלקה 894) או לפי שם של שמאי מכריע (לוי גלבוע). הממשק מתאים את עצמו אוטומטית.

🏢 זיהוי "אותו רחוב" חכם

כשמחפשים לפי גוש+חלקה, ה-Govmap מחזיר עסקאות מהפוליגון של הרחוב — אבל פוליגון יכול להכיל מספר רחובות. הפתרון שלנו: מציאת העסקה עם מספר חלקה הקרוב ביותר לחלקה המחופשת בתוך אותו גוש — סביר מאוד שהיא באותו רחוב. כך אנחנו מסמנים נכון מה "אותו רחוב" ומה "סביבה קרובה".

📊 שלוש רמות לשומות שמאי מכריע

כל חיפוש לפי גוש+חלקה מחזיר אוטומטית שלוש רמות:

  1. החלטות תואמות — בדיוק הגוש+חלקה שחיפשת
  2. החלטות נוספות באותו גוש — חלקות אחרות באותו גוש
  3. החלטות בגושים סמוכים — גוש ±2

דה-דופליקציה מובנית מבטיחה שהחלטה לא תופיע פעמיים.

📄 PDF Proxy

החלטות שמאי מכריע מאוחסנות בשרת ממשלתי שדורש header של x-client-id. דפדפן רגיל לא יכול להוריד אותן ישירות. הכלי מספק proxy endpoint שמטפל בזה — עם whitelist של hosts מותרים למניעת SSRF.

🛡️ עקיפת WAF של F5

ה-API של משרד המשפטים מוגן ב-WAF של F5 שחוסם בקשות "לא דפדפניות". הכלי משתמש ב-curl_cffi עם impersonation של Chrome 120 (TLS fingerprint תואם דפדפן אמיתי) כדי לעבור את ה-WAF.

🌐 RTL מלא

תמיכה מלאה בעברית — כולל DirectionProvider של Radix, dir="rtl" מפורש על body/tables/Tabs, ועיצוב Tailwind עם classes לוגיים (text-start/text-end/ms-*/me-*).

זיהוי חריגים (Outlier Detection)

ניתוחים סטטיסטיים משתמשים בפילטר IQR + סינון אחוזי + גבולות קשיחים, להסרת עסקאות עם נתונים שגויים (טעויות הקלדה, מכירות חלקיות, מקרים חריגים).


אופני חיפוש

חיפוש לפי כתובת

קטלב 5 צור הדסה
הילדסהיימר 14 תל אביב
ויצמן 10 חיפה

מחזיר את העסקאות באזור + השומות התואמות לגוש שזוהה.

חיפוש לפי גוש + חלקה

מתאים כשאין כתובת מדויקת או כשמחפשים פרצל גולמי:

גוש: 6212    חלקה: 894

פנימית, נשלח ל-Govmap בפורמט גוש N חלקה M (Govmap מזהה את הפורמט הזה ב-autocomplete).

חיפוש לפי שמאי מכריע

מציג את כל ההחלטות שאותו שמאי הכריע בהן:

לוי גלבוע
גלית עוזרי

לא מציג עסקאות (אין רלוונטיות אזורית).


ארכיטקטורה

┌────────────────────────────────────────────────────────────────┐
│                    דפדפן (React 19 + Vite)                     │
│  ─ SearchBar (3 modes)                                         │
│  ─ DealsTable (proximity inference, gush/חלקה columns)         │
│  ─ AppraisalsTable (3 tiers: exact / same block / nearby)      │
│  ─ TanStack Query, shadcn/ui, RTL DirectionProvider            │
└──────────────────────────────────┬─────────────────────────────┘
                                   │ REST + JSON
                                   ▼
┌────────────────────────────────────────────────────────────────┐
│                   FastAPI + FastMCP (Python 3.13)              │
│                                                                │
│  /api/search/address    ─→  Govmap autocomplete                │
│  /api/search/deals      ─→  Govmap deals (radius+polygon)      │
│  /api/search/appraisals ─→  gov.il SearchDecisions (3 tiers)   │
│  /api/appraisals/pdf    ─→  Streaming PDF proxy w/ x-client-id │
│  /mcp                   ─→  FastMCP streamable-http (LLMs)     │
│  /                      ─→  Static (React build)               │
└────────────────────────────────────────────────────────────────┘
                  │                          │
                  ▼                          ▼
       ┌──────────────────┐      ┌────────────────────────────┐
       │  www.govmap.gov  │      │ pub-justice.openapi.gov.il │
       │  (no auth)       │      │ (x-client-id header,       │
       │                  │      │  curl_cffi Chrome120 TLS)  │
       └──────────────────┘      └────────────────────────────┘

שכבות הקוד:

nadlan-mcp/
├── nadlan_mcp/
│   ├── fastmcp_server.py      # FastMCP tools (10) + clients
│   ├── web_app.py             # FastAPI app + REST endpoints + static
│   ├── config.py              # GovmapConfig + env vars
│   ├── govmap/                # Govmap API client (Pydantic v2 models)
│   │   ├── client.py          # HTTP, retry, rate limiting
│   │   ├── models.py          # Deal, AutocompleteResponse, etc.
│   │   ├── filters.py         # Deal filtering
│   │   ├── statistics.py      # Statistical analysis + outlier filtering
│   │   ├── market_analysis.py # Trends, comparables
│   │   └── outlier_detection.py
│   └── govil/                 # gov.il decisive-appraiser client
│       ├── client.py          # curl_cffi w/ Chrome impersonation
│       └── models.py          # AppraisalDecision, AppraisalDocument
├── web/                       # React 19 + Vite + shadcn/ui frontend
│   ├── src/
│   │   ├── App.tsx
│   │   ├── api/{client,types}.ts
│   │   └── components/
│   │       ├── SearchBar.tsx
│   │       ├── DealsTable.tsx
│   │       ├── AppraisalsTable.tsx
│   │       └── ui/            # shadcn-ui primitives (RTL-patched)
│   └── package.json
├── tests/                     # 314 tests, 84% coverage
├── Dockerfile                 # Multi-stage: node build → python runtime
└── .gitea/workflows/deploy.yaml  # CI/CD: build → registry → Coolify

התקנה והפעלה

דרישות

  • Python 3.13+
  • Node 22+ (לבניית ה-frontend)
  • pip / venv

הרצה לוקלית

# 1) שכפול
git clone https://gitea.dev.marcus-law.co.il/mcp-servers/nadlan-mcp.git
cd nadlan-mcp

# 2) Python — סביבה וירטואלית
python3 -m venv venv
source venv/bin/activate
pip install -e .

# 3) בניית ה-frontend
cd web
npm install
npm run build
cd ..

# 4) הרצת השרת
PORT=8000 python run_http_server.py

פתח ב-http://127.0.0.1:8000.

הרצה עם Docker

docker build -t nadlan-mcp .
docker run -p 8000:8000 nadlan-mcp

משתני סביבה

משתנה ברירת מחדל תיאור
PORT 8000 פורט השרת
GOVMAP_BASE_URL https://www.govmap.gov.il/api/ בסיס API של Govmap
GOVMAP_REQUESTS_PER_SECOND 5.0 rate-limit ל-Govmap
GOVMAP_MAX_RETRIES 3 retry exponential backoff
GOVMAP_DEFAULT_RADIUS 50 רדיוס ברירת מחדל (מטרים)
ANALYSIS_OUTLIER_METHOD iqr שיטת זיהוי חריגים (iqr/percent/none)
ANALYSIS_PRICE_PER_SQM_MIN 1000 גבול תחתון נמוך מדי למחיר/מ"ר
ANALYSIS_PRICE_PER_SQM_MAX 100000 גבול עליון

ראה רשימה מלאה ב-nadlan_mcp/config.py.


API Endpoints

כל ה-endpoints נחשפים תחת /api/ (גם /api/docs לתיעוד OpenAPI/Swagger).

GET /api/search/address?q=<query>

Autocomplete של כתובת — מחזיר קואורדינטות + גוש/חלקה אם זוהו.

curl "https://nadlan-mcp.dev.marcus-law.co.il/api/search/address?q=הילדסהיימר%2014%20תל%20אביב"

POST /api/search/deals

חיפוש עסקאות סביב כתובת.

{
  "address": "גוש 6212 חלקה 894",
  "years_back": 3,
  "radius_meters": 100,
  "max_deals": 50,
  "deal_type": 2
}

תגובה כוללת search.resolved_address (הטקסט המפוענח של Govmap), total, ו-deals[] עם השדות streetNameHeb, houseNum, gushNum, parcelNum, subParcelNum, deal_amount, asset_area, price_per_sqm, deal_source (same_building / street / neighborhood), ועוד.

POST /api/search/appraisals

חיפוש החלטות שמאי מכריע. כשמעבירים include_nearby: true עם block, מחזיר 3 buckets:

{
  "block": "6212",
  "plot": "894",
  "max_results": 30,
  "include_nearby": true,
  "nearby_block_radius": 2
}

תגובה:

{
  "total_in_db": 13420,
  "returned": 5,
  "decisions": [...],
  "same_block":    { "count": 12, "decisions": [...] },
  "nearby_blocks": { "count": 8,  "decisions": [...] }
}

GET /api/appraisals/pdf?url=<encoded>

Proxy ל-PDF של החלטה. רק hosts ב-whitelist (pub-justice.openapi.gov.il). הוסף &download=1 לכפיית הורדה.

/mcp

FastMCP streamable-http endpoint — לחיבור LLMs ו-AI agents.


פריסה (Deployment)

הפריסה ל-nadlan-mcp.dev.marcus-law.co.il אוטומטית דרך CI/CD:

git push → Gitea Actions →  build Docker image
                       →   push to private registry
                       →   trigger Coolify webhook
                       →   pull + redeploy

ראה .gitea/workflows/deploy.yaml.

Stack:

  • Coolify (orchestration)
  • Traefik 3.6 (reverse proxy + Let's Encrypt)
  • Docker registry פרטי
  • Python 3.13 slim image

פיתוח

בדיקות

# כל הבדיקות
pytest

# רק unit tests
pytest -m unit

# כיסוי
pytest --cov=nadlan_mcp

# בדיקת איכות מלאה (lint + format + tests)
./check-quality.sh

Linting

ruff format .       # פורמט
ruff check . --fix  # תיקון אוטומטי

פיתוח Frontend

cd web
npm run dev        # Vite dev server (HMR)
npm run typecheck  # tsc --noEmit
npm run lint

ניהול בעיות RTL

זיהינו והתגברנו על מספר בעיות RTL בדרך הקשה. אם אתה בונה אפליקציית React בעברית, מומלץ:

  1. הגדרה כפולה: <html dir="rtl"> וגם <body dir="rtl"> — חלק מהספריות בודקות את document.body.dir ולא את documentElement.
  2. CSS מפורש: html, body { direction: rtl; } ב-base layer של Tailwind.
  3. DirectionProvider: עטוף את ה-tree של React ב-<DirectionProvider dir="rtl"> של @radix-ui/react-direction. בלי זה, רכיבי Radix (Tabs, Dialog, Select, Popover) ברירת המחדל שלהם היא LTR.
  4. Tabs wrapper: עטוף את TabsPrimitive.Root עם default dir="rtl" כדי שגם אם DirectionProvider נמחק בעתיד, Tabs יישאר RTL.
  5. Tables: <table dir="rtl"> מפורש על כל טבלה — מבטיח סדר עמודות נכון בכל הדפדפנים.
  6. Logical classes: השתמש ב-text-start/text-end (לא text-left/text-right), ms-*/me-* (לא ml-*/mr-*), start-*/end-*. אבל זכור: ב-RTL, text-end מצמיד לשמאל, לא לימין.
  7. בדיקה ויזואלית בדפדפן לפני הצהרה ש-task UI הסתיים. build מוצלח לא מספיק.

רישוי

MIT — ראה LICENSE.


קישורים

S
Description
חיפוש עסקאות נדל"ן (Govmap) והחלטות שמאי מכריע (משרד המשפטים) — שרת MCP + ממשק Web עברי עם תמיכת RTL מלאה
Readme MIT 634 KiB
Languages
Python 90.6%
TypeScript 8.3%
Dockerfile 0.4%
JavaScript 0.3%
CSS 0.2%
Other 0.2%