Geospatial RAG + MCP Toolkit for Urban Intelligence
Built for SDG 11 workflows, pilot countries, and research-grade city analytics.
QUICK LINKS
Documentation | PyPI | Issues | MCP
PACKAGE
REPOSITORY
QUALITY
STANDARDS
TECH STACK
PLATFORM
- Abstract
- Executive Summary
- Overview
- Current Implementation Status
- Architecture
- Requirements
- Installation
- Quick Start
- Configuration
- CLI Reference
- MCP Integration
- Known Limitations
- Pilot Countries
- Mathematical Foundations
- API Summary
- Data Sources and Connectors
- WUF13 Alignment
- H3 Spatial Index
- Dependencies
- Data Flow
- Troubleshooting
- Glossary
- Frequently Asked Questions
- Version History
- Development
- Security Considerations
- Performance Notes
- References
- License
- Links
- Acknowledgments
CitySense is an open-source Python library for geospatial retrieval-augmented generation (RAG) and MCP-based AI tooling for urban analysis. It combines natural-language intent parsing, geospatial indexing, and an MCP server so applications can query urban context with minimal boilerplate. The project aligns with SDG 11, the New Urban Agenda, and WUF13 framing. The current codebase includes active pilot configs for Azerbaijan and Finland, OSM-powered indexing, and modular connectors for Sentinel-2, Mapillary, and KartaView integrations.
| Aspect | Description |
|---|---|
| Primary function | Semantic geospatial retrieval and MCP server for urban AI |
| Target users | Urban AI developers, smart city researchers, policy tool builders |
| Core technologies | Python 3.12+, Qdrant, Shapely, GeoPandas, H3, FastEmbed, FastMCP |
| Implemented pilots | Azerbaijan (az), Finland (fi) |
| Current indexing path | OSM -> H3 -> embeddings -> Qdrant |
| Standards alignment | WUF13 framing, SDG 11 indicator support |
| License | EUPL-1.2 |
The core design philosophy of CitySense is that a developer should be able to express spatial intent in natural language and receive structured geospatial results without writing spatial query code. For example:
# find housing zones with low resilience scores near transit corridors in BakuCitySense resolves such intent into structured geospatial results drawn from live and indexed sources.
CitySense adds a third observational layer on top of traditional vector geospatial data:
| Layer | Source | Purpose |
|---|---|---|
| Vector | OpenStreetMap, national registers | Buildings, roads, land use, amenities |
| Street-level imagery | Mapillary API v4, KartaView REST API | Ground truth, validation |
| Satellite | Copernicus Data Space, Sentinel Hub | Spectral indices, change detection |
| Capability | Description |
|---|---|
| Natural language queries | Intent parsing and semantic retrieval over geospatial knowledge bases |
| Multi-source architecture | OSM active CLI path; Sentinel-2, Mapillary, and KartaView connector modules included |
| MCP integration | Native Model Context Protocol server for Cursor, Claude, VS Code |
| WUF13 alignment | Pilot-aware schema and indicator model aligned to WUF13 framing |
| SDG 11 metrics | Land consumption rate (11.3.1), urban resilience composite score |
| Spectral indices | NDVI, NDWI, NDBI, EVI, MNDWI, BSI from Sentinel-2 L2A |
| Reciprocal Rank Fusion | Hybrid dense and sparse retrieval with configurable parameter k |
| Group | Use Case |
|---|---|
| Urban AI Developers | Build applications on city data with semantic access to geospatial knowledge bases |
| Smart City Researchers | Query, compare, and analyze datasets across multiple countries with consistent schemas |
| Urban Policy Tools Builders | Prototype AI-assisted planning tools aligned with UN New Urban Agenda, SDG 11, and WUF13 |
| Area | Status | Notes |
|---|---|---|
| CLI commands | Implemented | pilot, index, query, serve, --version |
| MCP tools | Implemented | query_spatial_context tool is available |
| Indexing connectors in CLI | Partially implemented | index build currently uses OSM connector path |
| Pilot country configs | Implemented | az, fi in citysense.pilot |
| Additional pilot profiles | Planned | se, dk, no are parsed in intent logic but not yet shipped as pilot configs |
| SSE transport | Placeholder | serve --transport sse currently prints status message |
+----------------------------------------------------------------------------------+
| CitySense Stack |
+------------------------------+---------------------------------------------------+
| CLI | RAG pipeline |
| - pilot (init/status) | parse_intent -> embed_texts -> hybrid_search -> |
| - index (build/status) | rerank -> assemble_context |
| - query | |
| - serve (stdio, sse stub) | |
+------------------------------+---------------------------------------------------+
| MCP server (FastMCP) | Connectors |
| - query_spatial_context | OSM (active path), Sentinel-2, Mapillary, |
| | KartaView (module-level support) |
+------------------------------+---------------------------------------------------+
| Storage and geo foundation: Qdrant + H3 + Shapely + GeoPandas |
+----------------------------------------------------------------------------------+
| Module | Responsibility |
|---|---|
| citysense.cli | Typer-based command-line interface |
| citysense.core | Configuration, session, logging, registry, exceptions |
| citysense.geo | CRS, H3, bbox, geometry, OSM utilities |
| citysense.connectors | OSM, Mapillary, KartaView, Sentinel, base connector |
| citysense.rag | Intent parsing, retriever, embedder, reranker, assembler |
| citysense.imagery | Street and satellite processing |
| citysense.housing | Housing analytics primitives |
| citysense.governance | Governance-related scoring hooks |
| citysense.urban | SDG 11 indicators |
| citysense.climate | Resilience scoring |
| citysense.realtime | Realtime stream utilities |
| citysense.pilot | Country-specific configurations |
| citysense.mcp | MCP server and tools |
| Principle | Implementation |
|---|---|
| Schema consistency | Pilot configs enforce national CRS and normalised GeoDataFrame schema |
| Extensibility | Connector and pilot registries allow plug-in modules |
| Observability | structlog for structured logging; configurable log levels |
| Type safety | mypy strict mode; Pydantic for config and data validation |
| Requirement | Version |
|---|---|
| Python | 3.12 or 3.13 |
| Qdrant | Default endpoint http://localhost:6333 |
| GDAL | 3.10+ (for rasterio, geopandas; conda recommended) |
pip install citysense| Extra | Purpose |
|---|---|
| clip | CLIP ViT-B/32 for street imagery embedding |
| sentinelhub | Sentinel Hub Process API |
| dev | ruff, mypy, pytest, mkdocs, pre-commit |
pip install "citysense[clip]"
pip install "citysense[dev]"For binary compatibility with GDAL, PROJ, GEOS:
conda env create -f environment.yml
conda activate citysense
pip install -e ".[dev]"git clone https://github.com/olaflaitinen/citysense.git
cd citysense
pip install -e ".[dev]"# 1) select pilot
citysense pilot init fi
# 2) build index (current CLI path: OSM)
citysense index build --city Helsinki --country fi --sources osm
# 3) check index status
citysense index status --country fi
# 4) run a natural-language query
citysense query "social housing zones within 1 km of metro stations in Helsinki"
# 5) start MCP server (stdio)
citysense serve --transport stdiopip install "citysense[clip]"
pip install "citysense[sentinelhub]"Then set connector credentials (MAPILLARY_ACCESS_TOKEN, CDSE_CLIENT_ID, CDSE_CLIENT_SECRET) as needed.
Configuration is read in priority order: environment variables (prefix CITYSENSE_), .env file at project root, defaults.
| Variable | Default | Description |
|---|---|---|
| CITYSENSE_PILOT_COUNTRY | None | Pilot key (az, fi fully available; se, dk, no reserved for upcoming profiles) |
| CITYSENSE_VECTOR_STORE_URL | http://localhost:6333 | Qdrant URL |
| CITYSENSE_EMBEDDING_MODEL | BAAI/bge-m3 | Text embedding model |
| MAPILLARY_ACCESS_TOKEN | None | Mapillary API token |
| CDSE_CLIENT_ID | None | Copernicus Data Space client ID |
| CDSE_CLIENT_SECRET | None | Copernicus Data Space client secret |
CITYSENSE_PILOT_COUNTRY=fi
CITYSENSE_VECTOR_STORE_URL=http://localhost:6333
MAPILLARY_ACCESS_TOKEN=your_token
CDSE_CLIENT_ID=your_id
CDSE_CLIENT_SECRET=your_secret
| Command | Description |
|---|---|
| citysense --version | Print package version |
| citysense pilot init <country> | Initialize pilot country in .env (az, fi, se, dk, no) |
| citysense pilot status | Show active pilot country |
| citysense index build --city <name> [--country <iso2>] | Build index for selected city |
| citysense index status [--country <iso2>] | Show Qdrant collection point count |
| citysense query <natural language> [--country <iso2>] [--city <name>] | Execute semantic spatial query |
| citysense serve --transport stdio | Start FastMCP server for local MCP clients |
| citysense serve --transport sse --port 7832 | SSE transport placeholder (status output) |
Notes:
index buildcurrently uses the OSM connector path.--sourcesis present for forward compatibility and not fully wired yet.index buildcity routing is currently optimized for Helsinki and Baku.
# Initialize Finland pilot
citysense pilot init fi
# Show current pilot status
citysense pilot status
# Build index for Helsinki (OSM path)
citysense index build --city Helsinki --country fi --sources osm
# Check index status in Qdrant
citysense index status --country fi
# Query with natural language
citysense query "metro stations within 500m of parks in Helsinki"
# Start MCP server for Cursor/Claude
citysense serve --transport stdio
# SSE transport status output (placeholder)
citysense serve --transport sseAdd to .cursor/mcp.json:
{
"mcpServers": {
"citysense": {
"command": "citysense",
"args": ["serve", "--transport", "stdio"],
"env": {
"CITYSENSE_PILOT_COUNTRY": "fi",
"CITYSENSE_VECTOR_STORE_URL": "http://localhost:6333",
"MAPILLARY_ACCESS_TOKEN": "your_token",
"CDSE_CLIENT_ID": "your_id",
"CDSE_CLIENT_SECRET": "your_secret"
}
}
}
}Add to claude_desktop_config.json:
{
"mcpServers": {
"citysense": {
"command": "citysense",
"args": ["serve", "--transport", "stdio"],
"env": {
"CITYSENSE_PILOT_COUNTRY": "az",
"CITYSENSE_VECTOR_STORE_URL": "http://localhost:6333"
}
}
}
}- Qdrant running at configured URL
- Index built:
citysense index build --city Helsinki --sources osm - Optional tokens for Mapillary and CDSE if imagery connectors are enabled
| Tool | Description |
|---|---|
| query_spatial_context | Execute natural language spatial query and return GeoJSON context |
| Transport | Use case |
|---|---|
| stdio | Cursor, Claude Desktop, local scripts |
| sse | Placeholder in current CLI; reserved for future remote clients |
citysense index buildcurrently indexes through the OSM connector path.- SSE transport is not a fully running server yet (
serve --transport sseis a placeholder output). - Pilot config modules currently shipped in code are
azandfi. - MCP server currently exposes one tool:
query_spatial_context.
| Country | Module Key | National CRS | Primary City |
|---|---|---|---|
| Azerbaijan | az | EPSG:32638 | Baku |
| Finland | fi | EPSG:3067 | Helsinki |
Planned pilot profiles (not yet shipped as config modules): Sweden (se), Denmark (dk), Norway (no).
| Attribute | Description |
|---|---|
| country | ISO2 code |
| language | IETF BCP 47 tag |
| national_crs | EPSG string |
| default_cities | City name to BBox mapping |
| connector_priority | Ordered connector IDs |
| wuf13_primary_dimensions | WUF13 dimension tags |
| data_gaps | Known gaps and fallback strategies |
| informality_heuristic | SAR/spectral heuristic for tenure |
All spectral indices are computed from Sentinel-2 L2A surface reflectance bands.
| Band ID | Centre Wavelength (nm) | Resolution (m) |
|---|---|---|
| B02 | 490 (Blue) | 10 |
| B03 | 560 (Green) | 10 |
| B04 | 665 (Red) | 10 |
| B08 | 842 (NIR broad) | 10 |
| B11 | 1610 (SWIR-1) | 20 |
| B12 | 2190 (SWIR-2) | 20 |
Range:
Open water:
Built-up:
Default:
where
| Dimension | Weight |
|---|---|
| Physical | 0.30 |
| Climate | 0.30 |
| Social | 0.20 |
| Infrastructure | 0.20 |
Default:
Default:
Sustainable urban growth: ratio approximately 1. Ratio
| Formula | Parameters | Default |
|---|---|---|
| RRF | k | 60 |
| Transit accessibility | r (radius), lambda (decay) | 800 m, 0.003 |
| URCS physical | alpha_s, alpha_a, alpha_SAR | 0.4, 0.35, 0.25 |
| URCS dimensions | w_physical, w_climate, w_social, w_infrastructure | 0.30, 0.30, 0.20, 0.20 |
from citysense.rag.intent import parse_intent, SpatialIntent
intent: SpatialIntent = parse_intent(
"social housing zones within 1 km of metro stations in Helsinki"
)
# intent.entity_types, intent.spatial_relations, intent.city_scope, ...from citysense.imagery.satellite.indices import compute_index, compute_ndvi
# From band dict (B02, B03, B04, B08, B11)
ndvi_array = compute_index("NDVI", bands)
ndwi_array = compute_index("NDWI", bands)from citysense.climate.resilience import compute_urcs, compute_physical_resilience
urcs = compute_urcs(physical=0.7, climate=0.6, social=0.5, infrastructure=0.8)
physical = compute_physical_resilience(
street_condition=0.8, building_age_norm=0.3, informality_score=0.1
)from citysense.urban.sdg11 import compute_sdg_1131, compute_land_consumption_rate
lcr = compute_land_consumption_rate(
urban_land_t0_km2=100, urban_land_t1_km2=120, years=10
)
ratio = compute_sdg_1131(
urban_land_t0_km2=100, urban_land_t1_km2=120,
pop_t0=1e6, pop_t1=1.2e6, years=10
)from citysense.pilot.az import AZ_CONFIG
from citysense.pilot.fi import FI_CONFIG
config = FI_CONFIG
print(config.country, config.national_crs, config.default_cities)| Connector | Data Type | API |
|---|---|---|
| OSM | Vector (buildings, roads, land use) | Overpass API |
| Sentinel-2 | Multispectral imagery | Copernicus Data Space, Sentinel Hub |
| Mapillary | Street-level imagery | Mapillary API v4 |
| KartaView | Street-level imagery | KartaView REST API |
| National registers | Cadastral, tenure | Country-specific |
Current CLI indexing path uses OSM. Other connectors are available as modules and are being wired into end-to-end CLI flows.
Pilot configurations define connector_priority to resolve conflicts when multiple sources provide overlapping data.
The 13th World Urban Forum (WUF13) dialogue dimensions inform CitySense pilot configurations and indicator coverage.
| Dimension | Description | CitySense Coverage |
|---|---|---|
| Adequate housing | Access to safe, affordable housing | Housing zone analysis, tenure heuristics |
| Urban planning | Land use, zoning, spatial planning | OSM land use, pilot city schemas |
| Climate action | Resilience, adaptation, mitigation | URCS, spectral indices, flood/heat risk |
| Urban economy | Employment, economic opportunity | Transit accessibility, service proximity |
| Urban ecology | Green space, biodiversity | NDVI, NDWI, built-up indices |
| Urban governance | Participation, transparency | Data standards, open schemas |
| Urban finance | Revenue, expenditure, investment | Indicator framework for fiscal analysis |
| Country | Known Gaps | Fallback Strategy |
|---|---|---|
| Azerbaijan | Peri-urban tenure | SAR texture + NDBI heuristic for informality |
| Finland | Informal settlements | Not applicable; use tenure from registers |
| Planned profiles (se, dk, no) | National profile tuning in progress | Add profile-specific data-gap maps during rollout |
The SpatialIntent dataclass captures parsed query slots from natural language input.
| Attribute | Type | Description |
|---|---|---|
| entity_types | tuple[str, ...] | OSM-style feature types (e.g. bus_stop, railway_station) |
| spatial_relations | tuple[str, ...] | Relations (e.g. near, within_500m) |
| attributes | dict[str, str] | Attribute filters (e.g. resilience: low) |
| country_scope | str | None | ISO2 country code |
| city_scope | str | None | City name |
| bbox | BBox | None | Resolved bounding box |
| wuf13_dimension | str | None | WUF13 dialogue dimension |
| sdg_indicator | str | None | SDG indicator code (e.g. 11.2.1) |
CitySense uses Uber H3 for hexagonal spatial indexing. Benefits include uniform cell size, hierarchical resolution, and efficient neighborhood queries.
| Resolution | Avg hexagon area (km^2) | Use case |
|---|---|---|
| 5 | 252.9 | City-scale analysis |
| 6 | 36.1 | District-scale |
| 7 | 5.2 | Neighborhood-scale |
| 8 | 0.74 | Block-scale |
| 9 | 0.11 | Building-scale |
H3 cells crossing the antimeridian require special handling. CitySense pre-filters queries to avoid invalid geometries.
| Package | Version | Purpose |
|---|---|---|
| shapely | >=2.1.2, <3.0 | Geometry operations |
| geopandas | >=1.1.2, <2.0 | Geospatial DataFrames |
| pyproj | >=3.7.1, <4.0 | Coordinate transformations |
| pyogrio | >=0.10.0 | Vector I/O |
| numpy | >=2.2.0, <3.0 | Numerical arrays |
| pandas | >=2.3.0, <4.0 | Tabular data |
| h3 | >=4.1.0, <5.0 | Hexagonal spatial index |
| rasterio | >=1.4.3, <2.0 | Raster I/O |
| xarray | >=2023.1.0 | Multidimensional arrays |
| pydantic | >=2.12.0, <3.0 | Data validation |
| pydantic-settings | >=2.7.0, <3.0 | Configuration |
| qdrant-client | >=1.17.0, <2.0 | Vector store client |
| fastembed | >=0.4.2, <1.0 | Embedding models |
| rank-bm25 | >=0.2.2 | BM25 sparse retrieval |
| litellm | >=1.57.0, <2.0 | LLM abstraction |
| mcp | >=1.4.0, <2.0 | Model Context Protocol |
| pystac-client | >=0.8.5, <1.0 | STAC catalog access |
| rio-cogeo | >=5.4.0, <8.0 | Cloud-optimized GeoTIFF |
| httpx | >=0.28.0, <1.0 | HTTP client |
| Pillow | >=11.1.0, <13.0 | Image processing |
| APScheduler | >=3.11.0, <4.0 | Task scheduling |
| structlog | >=25.1.0, <26.0 | Structured logging |
| typer | >=0.15.0, <1.0 | CLI framework |
| Extra | Packages | Purpose |
|---|---|---|
| clip | transformers, torch | CLIP ViT-B/32 for street imagery |
| sentinelhub | sentinelhub | Sentinel Hub Process API |
| dev | ruff, mypy, pytest, mkdocs, pre-commit | Development tooling |
City + country input
|
v
OSMConnector.fetch(bbox)
|
v
GeoDataFrame normalization
|
v
H3 assignment + chunk text
|
v
Embedding generation
|
v
Qdrant upsert
Natural-language query
|
v
parse_intent() -> SpatialIntent
|
v
embed_texts(query)
|
v
hybrid_search(Qdrant + BM25)
|
v
rerank(top_k)
|
v
assemble_context()
| Issue | Cause | Resolution |
|---|---|---|
| Qdrant connection refused | Qdrant not running | Start Qdrant: docker run -p 6333:6333 qdrant/qdrant |
| Index empty after build | Connector returned no data | Check city name, pilot config, OSM coverage |
| Mapillary 401 | Invalid or missing token | Set MAPILLARY_ACCESS_TOKEN |
| CDSE auth failure | Invalid credentials | Set CDSE_CLIENT_ID, CDSE_CLIENT_SECRET |
| CRS transform error | Mismatched EPSG | Verify pilot national_crs |
| H3 antimeridian error | Query crosses date line | Use bbox that does not span antimeridian |
| Term | Definition |
|---|---|
| RAG | Retrieval-Augmented Generation; augmenting LLM context with retrieved documents |
| MCP | Model Context Protocol; standard for AI tools and context |
| H3 | Uber hexagonal hierarchical spatial index |
| CRS | Coordinate Reference System |
| URCS | Urban Resilience Composite Score |
| LCR | Land Consumption Rate (SDG 11.3.1 numerator) |
| PGR | Population Growth Rate (SDG 11.3.1 denominator) |
| RRF | Reciprocal Rank Fusion |
| NDVI | Normalized Difference Vegetation Index |
| NDWI | Normalized Difference Water Index |
| NDBI | Normalized Difference Built-up Index |
| WUF13 | 13th World Urban Forum |
| SDG 11 | UN Sustainable Development Goal 11 (Sustainable Cities) |
CitySense is in Alpha (Development Status 3). Use for research, prototyping, and pilot deployments. Production hardening is ongoing.
Default: BAAI/bge-m3. Configurable via CITYSENSE_EMBEDDING_MODEL.
The MCP server and CLI work with any data source. Vector store (Qdrant) can be self-hosted. No data is sent to external services except configured APIs (Mapillary, CDSE, etc.).
Coverage excludes connectors and modules under active development. Run pytest tests/unit --cov=citysense --cov-report=term-missing for current metrics.
Yes. Add a new PilotConfig module under citysense.pilot, expose it in package imports, and extend CLI validation logic for country codes. See CONTRIBUTING.md.
| Version | Date | Highlights |
|---|---|---|
| 0.2.1 | 2026-02 | Current alpha release; core RAG pipeline, FastMCP server, and pilot configs for AZ/FI |
| 0.2.0 | 2026-02-28 | Initial WUF13-aligned specification baseline |
| Unreleased | - | Additional pilot profiles, richer MCP tool surface, expanded connector wiring |
git clone https://github.com/olaflaitinen/citysense.git
cd citysense
pip install -e ".[dev,clip]"
pre-commit installruff check src tests
ruff format --check src tests
mypy src/citysensepytest tests/unit -v
pytest tests/unit -v --cov=citysense --cov-report=term-missingmkdocs serve| Area | Description |
|---|---|
| Country connectors | Additional WUF13-relevant cities and national data sources |
| Non-Latin script | Arabic, Cyrillic handling for Azerbaijan and Central Asia |
| Informal settlement detection | Model improvements for tenure heuristics |
| Climate adaptation | Document parsers for national plans |
| Python | Status |
|---|---|
| 3.12 | Supported, tested in CI |
| 3.13 | Supported, tested in CI |
| 3.11 | Not supported (requires 3.12+) |
| Type | Version Bump | Example |
|---|---|---|
| feat: | Minor | feat(imagery): add Sentinel-3 LST connector |
| fix: | Patch | fix(rag): correct H3 pre-filter for antimeridian |
| feat!: | Major | feat!: remove deprecated search() method |
| docs:, chore:, test: | None | docs: add Baku pilot tutorial |
| Concern | Mitigation |
|---|---|
| API tokens | Store in environment variables or secrets; never commit |
| Qdrant | Run locally or in private network; no default auth |
| Data provenance | All connectors document source and license |
| Dependency audit | Dependabot enabled; run pip audit periodically |
| Operation | Typical scale | Notes |
|---|---|---|
| Index build (OSM, city) | 10k-100k features | Depends on city size, H3 resolution |
| Query latency | 100-500 ms | Dense + sparse + RRF; reranker adds ~50 ms |
| Embedding | BAAI/bge-m3 | ~50 docs/s on CPU; GPU accelerates |
| Qdrant | Local | Sub-10 ms for vector search at city scale |
- McFeeters, S. K. (1996). The use of the Normalized Difference Water Index (NDWI) in the delineation of open water features. International Journal of Remote Sensing, 17(7), 1425-1432.
- Zha, Y., Gao, J., & Ni, S. (2003). Use of normalized difference built-up index in automatically mapping urban areas from TM imagery. International Journal of Remote Sensing, 24(3), 583-594.
- Huete, A., et al. (2002). Overview of the radiometric and biophysical performance of the MODIS vegetation indices. Remote Sensing of Environment, 83(1-2), 195-213.
- Rikimaru, A., Roy, P. S., & Miyatake, S. (2002). Tropical forest cover density mapping. Tropical Ecology, 43(1), 39-47.
- UN-Habitat. (2020). SDG Indicator 11.3.1 - Land consumption rate. United Nations.
- UN-Habitat. (2020). SDG Indicator 11.2.1 - Proportion of population with convenient access to public transport. United Nations.
- Cormack, G. V., Clarke, C. L., & Buettcher, S. (2009). Reciprocal rank fusion outperforms condorcet and individual rank learning methods. SIGIR 2009.
If you use CitySense in academic work, please cite:
CitySense: Geospatial RAG and MCP Server for Urban AI Development.
Specification v0.2.1. WUF13 Aligned. 2026.
https://github.com/olaflaitinen/citysense
| Index | Low | Medium | High | Interpretation |
|---|---|---|---|---|
| NDVI | < 0.1 | 0.1-0.3 | > 0.3 | Vegetation density |
| NDWI | < 0 | 0 | > 0 | Open water presence |
| NDBI | < 0 | 0 | > 0 | Built-up intensity |
| EVI | < 0.2 | 0.2-0.4 | > 0.4 | Enhanced vegetation |
| BSI | < 0 | 0 | > 0 | Bare soil / impervious |
EUPL-1.2. See LICENSE.
| Resource | URL |
|---|---|
| Documentation | citysense.readthedocs.io |
| Repository | github.com/olaflaitinen/citysense |
| Issues | github.com/olaflaitinen/citysense/issues |
| Changelog | CHANGELOG.md |
| Contributing | CONTRIBUTING.md |
| Security | SECURITY.md |
CitySense builds on open standards and community data: OpenStreetMap contributors, Copernicus Programme, Mapillary, KartaView, Qdrant, and the Model Context Protocol initiative. Pilot country configurations align with national spatial data infrastructures and WUF13 dialogue priorities.