《城市守护者》(以色列)
用于以色列房地产情报的MCP服务器和REST API --地理编码、地籍数据、城市规划以及来自官方政府空间资源的双语咨询报告。
______________________________________________________________________
概述
城市守护者是 模型上下文协议(MCP)服务器 这暴露了工具 AI代理和应用程序 查询以色列地址并接收结构化数据:WGS84坐标、街区/地块(Gush/Helka)、分区计划、建筑许可证和综合风险/机遇报告。A. REST API 反映了集成和手动测试的相同操作。该系统设计用于 生产风格 架构:MCP和REST之间的共享实现,全面的测试(单元、E2E、与真实GovMap/Nominatim API的集成),以及客户端逻辑、服务器工具和API层的清晰分离。
观众: 作为一个组合项目构建,展示 后端工程 (API设计、外部API集成、验证、错误处理)和 AI/LLM集成 (MCP协议,LLM消费工具设计)。
______________________________________________________________________
特性
- MCP服务器 --六种工具:
geocode_address,get_cadastral_data,get_urban_plans,get_spatial_mining,get_multi_radius_search,generate_guardian_report(FastMCP,标准化)。 - REST API --通过HTTP(FastAPI)进行相同的操作,包括验证和400无效输入。
- GovMap和地理编码 --地址规范化、WGS84验证(以色列bbox)、具有可配置URL的GovMap客户端; 提名(OSM)回退 当GovMap返回非JSON或无结果时(仅限以色列)。
- 结构化响应 --GeoJSON和平面字典解析;“你是说?”找不到地址建议。
- 🔍 API完全透明 --每个响应都包含来自GovMap/Nomingim API的完整原始数据
raw_api_response和raw_api_data领域。零过滤-用户收到100%的政府API响应,包括所有属性、功能和元数据。 - 测试 -单元(模拟)、功能、E2E(“关注购房者”场景)、集成(真实GovMap getTypes、Nomatim)、REST API测试;单元与集成的pytest标记。
- 邮递员 --收集所有REST端点和错误情况。
______________________________________________________________________
技术栈
| 层 | 技术 |
|---|---|
| MCP服务器 | 快速MCP (Python),标准操作系统 |
| REST API | FastAPI,Uvicorn |
| HTTP客户端 | httpx |
| 地理编码 | GovMap(可配置);GovMap不可用时的提名回退 |
| 测试 | pytest,pytest-cov |
| Package/env | uv,pyproject.toml(Python≥3.10) |
数据来源: 所有规划和地籍数据均来自 仅限政府地图 (GeoServer WFS和GovMap API)。该系统已通过GovMap全面实施并运行。
实施状态
| 工具/API | 状态 | |
|---|---|---|
| 地理地址 | 政府地图优先; 提名(OSM)回退 当GovMap不可用或返回非JSON(例如HTML)时。结果可能包括 "source": "nominatim" 当使用回退时。 | |
| get_cadastraldata | 政府地图WFS 地籍层(וש/חל\\1511 ;ה)——在点上识别;返回街区(Gush)和包裹(Helka)。 | |
| 城市规划 | 政府地图WFS | plans/permits at coordinates(坐标上的计划/许可证)。 |
| get_spatial_mining | 车站3 --半径为100米、500米、1000米的计划/许可证(许可证、基础设施背景) | |
| get_multi_radius_search | 多半径搜索 --分层半径:卧室50米,允许100米,生活方式300米,计划500米,价值800米;大脑的摘要标志。 | |
| 发电机_保护器_报告 | 监护人得分 --地籍+多半径计划/许可的加权分析(优点、风险、状态)+ 噪音+TAMA+交通;返回0-100分,咨询、报告、风险、机遇,以及详细的环境数据。 |
______________________________________________________________________
建筑
生产线(4站)
从用户查询到咨询报告的端到端流程:
| 站 | 名称 | 输入 | 发生了什么 | 输出 |
|---|---|---|---|---|
| 1 | 地理编码 | “דיזנ\\1493;י100,άל1488;άי” | 政府地图(或提名)转换地址→ 点 | 纬度、经度、显示名称 |
| 2 | Cadastral (Identify) | Lat, Lon | GovMap WFS on 团体/部分层 | Gush (团体), Helka (部分) — Tabu legal ID |
| 3 | 空间采矿 | Lat,Lon | GovMap WFS在100米、500米、1000米处的计划/许可 | within_100m, within_500m, within_1000m |
| 4 | 大脑 | 1-3的原始JSON | 加权分析(Guardian评分) | 报告:评分、风险、机遇、咨询 |
工具: 车站1 → geocode_address; 车站2 → get_cadastral_data; 车站3 → get_urban_plans + get_spatial_mining + get_multi_radius_search (基于层的半径); 车站4 → generate_guardian_report (卫报评分——加权分析)。
监护人评分(加权分析)
4号站将三个矢量聚合成一个 监护人得分 (0–100)和短 咨询:
- 优点(Pros): 地籍已确定,100米范围内无许可证,500米范围内有开放空间/住宅分区,规划多样。
- 风险: 50米/100米范围内的施工许可证(噪音)、拟建道路、附近的重型商业区。
- 状态: 规划清晰(地块已标识)或未标识/限制。
这 决策矩阵 (每个条件增加/减少点数)在 guardian_score.py 并记录了AI在 docs/GUARDIAN_SCORE_MATRIX.md.那份文件兼作 系统提示 因此,当AI(例如Claude)具有原始MCP输出时,它可以应用相同的规则。API返回 guardian_score, consult, report, risks, opportunities,可选 score_breakdown, status, status_note.
活动流(端到端)
用户或AI客户端发送地址(或坐标)。入口点是 MCP服务器 或 REST API第一阶段对地址进行地理编码;第二阶段获取地籍和规划数据;第三阶段产生监护人报告。
flowchart TB
subgraph User["User / AI Client"]
A[User query: address or coordinates]
end
subgraph Entry["Entry Points"]
MCP[MCP Server]
REST[REST API]
end
subgraph Phase1["Phase 1 — Geographic Foundation"]
B[geocode_address]
B1{Address valid?}
B2[clean_address]
B3[GovMap / Nominatim]
B4[Return lat, lon]
B5[Return error + suggestions]
end
subgraph Phase2["Phase 2 — Cadastral & Planning"]
C[get_cadastral_data]
D[get_urban_plans]
C1[GovMap WFS]
D1[GovMap WFS]
end
subgraph Phase3["Phase 3 — Urban Intelligence"]
E[generate_guardian_report]
E1[Guardian Score]
E2[Report, consult]
end
subgraph External["External Systems"]
GovMap[GovMap API / GeoServer WFS]
end
A --> MCP
A --> REST
MCP --> B
REST --> B
B --> B1
B1 -->|Yes| B2
B2 --> B3
B3 --> GovMap
B3 --> B4
B1 -->|No / empty| B5
B4 --> C
B4 --> D
C --> C1
D --> D1
C1 --> GovMap
D1 --> GovMap
C --> E
D --> E
E --> E1
E1 --> E2简化流程(快乐之路)
flowchart LR
A[Address query] --> B[geocode_address]
B --> C[get_cadastral_data]
B --> D[get_urban_plans]
C --> E[generate_guardian_report]
D --> E
E --> F[Report: risks & opportunities]E2E序列:“忧心忡忡的购房者”
sequenceDiagram
participant User
participant MCP as MCP / REST API
participant GovMap
User->>MCP: "22 HaNevi'im St, Jerusalem"
MCP->>MCP: geocode_address
MCP->>GovMap: search (or Nominatim)
GovMap-->>MCP: lat, lon (WGS84)
MCP-->>User: latitude, longitude
MCP->>MCP: get_cadastral_data(lat, lon)
MCP->>GovMap: WFS cadastral layers
GovMap-->>MCP: gush, helka
MCP-->>User: gush, helka
MCP->>MCP: get_urban_plans(lat, lon)
MCP->>GovMap: WFS plans/permits
GovMap-->>MCP: plans, permits
MCP-->>User: plans[], permits[]
MCP->>MCP: generate_guardian_report(lat, lon, address, language)
MCP-->>User: report, risks[], opportunities[]类/模块结构
MCP工具和REST端点共享相同的 _impl 功能。唯一的自定义例外是 AddressNotFoundError 在GovMap客户端中。
classDiagram
direction TB
class FastMCP {
>
+tool geocode_address(address)
+tool get_cadastral_data(lat, lon)
+tool get_urban_plans(lat, lon)
+tool generate_guardian_report(lat, lon, address?, language?)
}
class server_module {
>
_geocode_address_impl(address)
_get_cadastral_data_impl(lat, lon)
_get_urban_plans_impl(lat, lon)
_generate_guardian_report_impl(lat, lon, address?, language?)
}
class AddressNotFoundError {
>
+message: str
+suggestions: list
}
class govmap_client_module {
>
clean_address(address)
validate_coordinates_in_israel(lat, lon)
search_address(address)
_parse_one_result(r)
_parse_govmap_response(data)
}
class FastAPI_app {
>
GET /health
POST /geocode_address
POST /get_cadastral_data
POST /get_urban_plans
POST /generate_guardian_report
}
class GovMap_API { > }
FastMCP --> server_module : uses _*_impl
server_module --> govmap_client_module : search_address
server_module ..> AddressNotFoundError : catches
govmap_client_module --> AddressNotFoundError : raises
govmap_client_module --> GovMap_API : HTTP
FastAPI_app --> server_module : uses _*_impl
server_module ..> GovMap_API : get_cadastral_data, get_urban_plans数据流(响应形状)
classDiagram
class GeocodeResult {
>
+latitude: float
+longitude: float
+display_name: str?
or error: str
or suggestions: list
}
class CadastralResult {
>
+gush: int?
+helka: int?
+note: str
}
class UrbanPlansResult {
>
+plans: list
+permits: list
+note: str
}
class GuardianReportResult {
>
+report: str?
+risks: list
+opportunities: list
+language: "en"|"he"
+note: str
}
GeocodeResult --> CadastralResult : lat, lon
GeocodeResult --> UrbanPlansResult : lat, lon
CadastralResult --> GuardianReportResult : input
UrbanPlansResult --> GuardianReportResult : input______________________________________________________________________
项目结构
| 路径 | 角色 |
|---|---|
server.py | MCP服务器(FastMCP):工具定义和 _*_impl 实施。 |
govmap_client.py | GovMap客户端:地址规范化、验证、搜索、响应解析, AddressNotFoundError. |
api.py | REST API(FastAPI): /health, /geocode_address, /get_cadastral_data, /get_urban_plans, /generate_guardian_report. |
tests/ | 单元、功能、E2E、集成和REST API测试。 |
postman/ | REST API的Postman集合。 |
docs/ | 附加文档(例如PROJECT_OVERVIEW)。 |
pyproject.toml | 项目元数据和依赖关系(uv)。 |
______________________________________________________________________
入门
先决条件: Python≥3.10, 紫外线 (推荐)或pip。
运行MCP服务器
# With uv (creates .venv and installs deps from pyproject.toml)
uv run server.py使用pip:
pip install -r requirements.txt
fastmcp run server.py运行REST API
uvicorn api:app --reload --port 8000- 健康:
GET http://localhost:8000/health - 邮递员: 导入 邮递员/Urban_Guadian_API.postman_collection.json;基本URL
http://localhost:8000.
REST端点(摘要)
| 方法 | 端点 | 正文(JSON) |
|---|---|---|
| 得到 | /health | — |
| 职位 | /geocode_address | {"address": "22 HaNevi'im St, Jerusalem"} |
| 职位 | /get_cadastral_data | {"latitude": 31.784, "longitude": 35.221} |
| 职位 | /get_urban_plans | {"latitude": 31.784, "longitude": 35.221} |
| 职位 | /get_spatial_mining | {"latitude": 31.784, "longitude": 35.221} (可选: radius_permits_m, radius_plans_m, radius_infrastructure_m) |
| 职位 | /get_multi_radius_search | {"latitude": 31.784, "longitude": 35.221} --基于层的半径(50/100/300/500/800米),汇总标志 |
| 职位 | /generate_guardian_report | {"latitude": 31.784, "longitude": 35.221, "address": "...", "language": "en"} |
GovMap配置
GovMap端点和图层名称记录在 docs/GOVMAP_INTEGRATION.md (API官方文件,网址: api.govmap.gov.il/docs 可能返回“拒绝访问”)。可选环境变量:
| 变量 | 默认值 | 描述 |
|---|---|---|
GOVMAP_SEARCH_URL | https://www.govmap.gov.il/Searching/SearchRest.ashx | 地理编码搜索端点。 |
GOVMAP_PLAN_LAYERS | govmap:layer_tabaot,govmap:layer_retzefmigrashim,govmap:layer_retzefgvulot | 以逗号分隔的WFS图层名称用于平面图 |
GOVMAP_CADASTRAL_LAYERS | govmap:layer_parcel_all,... | 地籍用逗号分隔的WFS图层名称(וש/חל\\1511 ;ה)。 |
GOVMAP_PERMIT_LAYERS | (empty) | 建筑许可证的逗号分隔层名称。 |
GOVMAP_NOISE_LAYERS | govmap:layer_svivanoiseday,govmap:layer_svivanoisenight | 噪声污染层(白天/晚上)。 |
GOVMAP_TAMA_LAYERS | govmap:layer_tamat_investor_informetion,... | TAMA 38层城市更新。 |
GOVMAP_TRANSPORT_LAYERS | (空) | 交通基础设施层(地铁、铁路)。 |
GOVMAP_CONSERVATION_LAYERS | (空) | 保护和遗产层(市政)。 |
GOVMAP_HAZARDS_LAYERS | (空) | 危险层(高压、环境)。 |
______________________________________________________________________
测试
# All tests
uv run pytest tests/ -v
# or: pip install -r requirements.txt && python -m pytest tests/ -v
# Unit only (no real external APIs)
uv run pytest -m "not integration" -v
# Integration (real GovMap getTypes, Nominatim)
uv run pytest tests/test_integration_real_api.py -v| 测试模块 | 覆盖范围 |
|---|---|
test_geocode.py | GovMap客户端:clean_address、validate_coordings、search_address(有效、未找到、建议、空、GeoJSON);地理编码工具成功/错误。 |
test_server.py | 地籍、城市规划、监护人报告(形状、WGS84、语言、地址);MCP工具注册(所有四个工具)。 |
test_e2e.py | E2E“关注购房者”:完整的工作流程;成功标准(精确性、可操作的输出、双语);报告结构。 |
test_integration_real_api.py | Real GovMap getTypes,GovMap URL可达,Nominim地理编码(耶路撒冷,特拉维夫),具有真实地理编码的E2E(@pytest.mark.integration). |
test_api.py | REST API:健康、地理代码/地籍/计划/报告(成功+无效主体→ 400). |
______________________________________________________________________
阶段(路线图)
| 阶段 | 名称 | 状态 |
|---|---|---|
| 1 | 地理基金会(GovMap地理编码,ITM→WGS84)✅ 功能性 | |
| 2 | 地籍与规划(Gush/Helka、Hostel-Hotel、许可证) | GovMap WFS/API |
| 3 | 城市情报(风险/机遇综合,双语报告) | 📋 逻辑定义 |
| 4 | 环境和基础设施(邻近、洪水/地震) | 🚀 计划中 |
______________________________________________________________________
示例:AI/Claude用例
用户: *“分析特拉维夫HaYarkon 10的发展潜力。”*
- 地理编码 —
geocode_address("HaYarkon 10, Tel Aviv")→ 纬度、经度(WGS84)。 - 地籍 —
get_cadastral_data(lat, lon)→ 地块(Gush)、地块(Helka)。 - 规划 —
get_urban_plans(lat, lon)→ 计划和许可证(GovMap WFS)。 - 报告 —
generate_guardian_report(lat, lon, address=..., language="en")→ 监护人评分(0-100)、咨询、报告、风险、机会、评分分解、状态。
MCP服务器将这些作为工具公开,以便AI代理可以按顺序调用它们;REST API为HTTP客户端公开相同的操作。
______________________________________________________________________
文档
- 项目_奥维德.md --详细的阶段分解、数据源和工具语义(适合作为系统提示或项目简报)。
- 图表 --活动流程、序列和类图在这个README(Mermaid)中。它们在GitHub、GitLab和支持Mermaid的编辑器中呈现;您还可以将块粘贴到 美人鱼直播 编辑或导出。
______________________________________________________________________
许可证
请参阅存储库设置。该项目用于组合和演示目的。
