Skip to main content

Geospatial RAG and MCP server for urban AI development; WUF13 aligned.

Project description

CitySense Logo

CitySense

PyPI version PyPI - Python Version PyPI - Downloads PyPI - Format PyPI - License PyPI - Status PyPI - Wheel CI OpenSSF Scorecard codecov Python License Ruff mypy Read the Docs Pre-commit Qdrant OpenStreetMap SDG 11 MCP Shapely GeoPandas

Geospatial RAG and MCP Server Library for Urban AI Development

Specification v0.2.0 | February 2026 | WUF13 Aligned


Table of Contents

  1. Abstract
  2. Executive Summary
  3. Overview
  4. Architecture
  5. Requirements
  6. Installation
  7. Quick Start
  8. Configuration
  9. CLI Reference
  10. MCP Integration
  11. Pilot Countries
  12. Mathematical Foundations
  13. API Summary
  14. Data Sources and Connectors
  15. WUF13 Alignment
  16. SpatialIntent Structure
  17. H3 Spatial Index
  18. Dependencies
  19. Data Flow
  20. Troubleshooting
  21. Glossary
  22. Frequently Asked Questions
  23. Version History
  24. Development
  25. Security Considerations
  26. Performance Notes
  27. References
  28. License
  29. Links

Abstract

CitySense is an open-source Python library that bridges geospatial urban data with large language model (LLM) toolchains. It provides two tightly integrated components: a geospatial retrieval-augmented generation (RAG) framework that semantically indexes spatial datasets and retrieves relevant context for natural language queries, and a Model Context Protocol (MCP) server that exposes city intelligence directly into AI-assisted development environments. The library is aligned with the United Nations Sustainable Development Goal 11 (Sustainable Cities and Communities), the New Urban Agenda, and the 13th World Urban Forum (WUF13) dialogue dimensions. CitySense supports five pilot countries (Azerbaijan, Finland, Sweden, Denmark, Norway) with consistent schemas and national coordinate reference systems. The framework implements spectral indices (NDVI, NDWI, NDBI, EVI, MNDWI, BSI) from Sentinel-2 L2A, Reciprocal Rank Fusion for hybrid retrieval, Urban Resilience Composite Score, and SDG 11.3.1 Land Consumption Rate. Street-level imagery (Mapillary, KartaView) and multispectral satellite data (Copernicus Data Space, Sentinel Hub) extend traditional vector geospatial analysis.


Executive Summary

Aspect Description
Primary function Semantic geospatial retrieval and MCP server for urban AI
Target users Urban AI developers, smart city researchers, urban policy tools builders
Core technologies Python 3.12+, Qdrant, Shapely, GeoPandas, H3, fastembed, MCP
Data sources OpenStreetMap, Sentinel-2, Mapillary, KartaView, Copernicus Data Space
Standards alignment WUF13, SDG 11, UN New Urban Agenda
License EUPL-1.2

Overview

Design Philosophy

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 Baku

CitySense resolves such intent into structured geospatial results drawn from live and indexed sources.

Observational Layers

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

Key Features

Capability Description
Natural language queries Intent parsing and semantic retrieval over geospatial knowledge bases
Multi-source indexing OpenStreetMap, Sentinel-2, Mapillary, KartaView, national registers
MCP integration Native Model Context Protocol server for Cursor, Claude, VS Code
WUF13 alignment Pilot countries with consistent schemas and national CRS
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

Primary User Groups

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

Architecture

System Stack

┌─────────────────────────────────────────────────────────────────────────────┐
│                           CitySense Stack                                    │
├─────────────────────────────────────────────────────────────────────────────┤
│  CLI (citysense)                                                             │
│  pilot init | index build | query | serve | export | imagery | watch         │
├─────────────────────────────────────────────────────────────────────────────┤
│  MCP Server (stdio/SSE)              │  Geospatial RAG Pipeline               │
│  Tools: query_spatial_context,      │  Intent Parser → H3 Filter →            │
│  analyze_housing_zone,              │  Dense Retrieval + Sparse (BM25) →       │
│  get_resilience_score, bounds       │  RRF Fusion → Reranker → Assembler      │
├─────────────────────────────────────────────────────────────────────────────┤
│  Connectors: OSM, Sentinel-2, Mapillary, KartaView, CDSE                    │
├─────────────────────────────────────────────────────────────────────────────┤
│  Vector Store (Qdrant)  │  Geometry (Shapely, GeoPandas, H3)                 │
└─────────────────────────────────────────────────────────────────────────────┘

Module Structure

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.urban SDG 11 indicators
citysense.climate Resilience scoring
citysense.pilot Country-specific configurations
citysense.mcp MCP server and tools

Design Principles

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

Requirements

Requirement Version
Python 3.12 or 3.13
Qdrant Default endpoint http://localhost:6333
GDAL 3.10+ (for rasterio, geopandas; conda recommended)

Installation

pip

pip install citysense

Optional Extras

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]"

conda-forge (Binary Compatibility)

For binary compatibility with GDAL, PROJ, GEOS:

conda env create -f environment.yml
conda activate citysense
pip install -e ".[dev]"

Editable Install

git clone https://github.com/olaflaitinen/citysense.git
cd citysense
pip install -e ".[dev]"

Quick Start

Minimal Workflow

citysense pilot init fi
citysense index build --city Helsinki --sources osm
citysense query "social housing zones within 1 km of metro stations in Helsinki"
citysense serve --transport stdio

With Imagery (CLIP)

pip install "citysense[clip]"
citysense pilot init fi
citysense index build --city Helsinki --sources osm,mapillary

With Sentinel Hub

pip install "citysense[sentinelhub]"
# Set SENTINELHUB_INSTANCE_ID, SENTINELHUB_CLIENT_ID, SENTINELHUB_CLIENT_SECRET
citysense index build --city Baku --sources osm,sentinel

Configuration

Configuration is read in priority order: environment variables (prefix CITYSENSE_), .env file at project root, defaults.

Environment Variables

Variable Default Description
CITYSENSE_PILOT_COUNTRY None Pilot module key: az, fi, se, dk, no
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

Example .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

CLI Reference

Command Description
citysense pilot init <country> Initialize pilot configuration
citysense index build --city <name> --sources <list> Build vector index
citysense query <natural language> Execute semantic spatial query
citysense serve --transport stdio Start MCP server (stdio)
citysense serve --transport sse Start MCP server (SSE)
citysense export <format> Export indexed data
citysense imagery <subcommand> Street/satellite imagery operations
citysense watch Watch mode for real-time updates

CLI Examples

# Initialize Finland pilot
citysense pilot init fi

# Build index for Helsinki from OSM only
citysense index build --city Helsinki --sources osm

# Build index with multiple sources (requires tokens)
citysense index build --city Baku --sources osm,mapillary,sentinel

# Query with natural language
citysense query "metro stations within 500m of parks in Stockholm"

# Start MCP server for Cursor/Claude
citysense serve --transport stdio

# Start MCP server with SSE for web clients
citysense serve --transport sse

MCP Integration

Cursor

Add 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"
      }
    }
  }
}

Claude Desktop

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"
      }
    }
  }
}

Prerequisites

  1. Qdrant running at configured URL
  2. Index built: citysense index build --city Helsinki --sources osm
  3. API tokens for Mapillary and CDSE if using imagery

MCP Tools

Tool Description
query_spatial_context Execute natural language spatial query and return GeoJSON context
analyze_housing_zone Analyze housing zone with resilience and SDG metrics
get_resilience_score Compute URCS for a given location or zone
get_bounds Return bounding box for pilot city or region

Transport Modes

Transport Use case
stdio Cursor, Claude Desktop, local scripts
sse Web applications, remote clients

Pilot Countries

Country Module Key National CRS Primary City
Azerbaijan az EPSG:32638 Baku
Finland fi EPSG:3067 Helsinki
Sweden se EPSG:3006 Stockholm
Denmark dk EPSG:25832 Copenhagen
Norway no EPSG:25833 Oslo

Pilot Configuration Attributes

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

Mathematical Foundations

Sentinel-2 Band Reference

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

Spectral Indices

NDVI (Normalized Difference Vegetation Index)

$$\mathrm{NDVI} = \frac{\rho_{\mathrm{NIR}} - \rho_{\mathrm{Red}}}{\rho_{\mathrm{NIR}} + \rho_{\mathrm{Red}}} = \frac{B_{08} - B_{04}}{B_{08} + B_{04}}$$

Range: $[-1, +1]$. Urban green: $> 0.3$. Built-up: $< 0.1$.

NDWI (McFeeters 1996)

$$\mathrm{NDWI} = \frac{B_{03} - B_{08}}{B_{03} + B_{08}}$$

Open water: $> 0.0$.

NDBI (Zha et al. 2003)

$$\mathrm{NDBI} = \frac{B_{11} - B_{08}}{B_{11} + B_{08}}$$

Built-up: $> 0.0$.

EVI (Huete et al. 2002)

$$\mathrm{EVI} = 2.5 \cdot \frac{B_{08} - B_{04}}{B_{08} + 6 \cdot B_{04} - 7.5 \cdot B_{02} + 1}$$

MNDWI (Modified NDWI)

$$\mathrm{MNDWI} = \frac{B_{03} - B_{11}}{B_{03} + B_{11}}$$

BSI (Rikimaru et al. 2002)

$$\mathrm{BSI} = \frac{(B_{11} + B_{04}) - (B_{08} + B_{02})}{(B_{11} + B_{04}) + (B_{08} + B_{02})}$$

Reciprocal Rank Fusion

$$\mathrm{RRF}(d) = \sum_{R \in {R_{\mathrm{dense}}, R_{\mathrm{sparse}}}} \frac{1}{k + \mathrm{rank}_R(d)}$$

Default: $k = 60$.

Cross-Encoder Reranking

$$s_i = \mathrm{CrossEncoder}(q, c_i)$$

Urban Resilience Composite Score

$$\mathrm{URCS}(c) = \sum_{d \in D} w_d \cdot R_d(c)$$

where $D = {\mathrm{physical}, \mathrm{climate}, \mathrm{social}, \mathrm{infrastructure}}$.

Dimension Weight $w_d$
Physical 0.30
Climate 0.30
Social 0.20
Infrastructure 0.20

Physical Resilience Sub-dimension

$$R_{\mathrm{physical}} = \alpha_s \cdot s_{\mathrm{condition}} + \alpha_a \cdot (1 - a_{\mathrm{norm}}) + \alpha_{\mathrm{SAR}} \cdot (1 - I_{\mathrm{informal}})$$

Default: $\alpha_s = 0.4$, $\alpha_a = 0.35$, $\alpha_{\text{SAR}} = 0.25$.

Segregation Indices

Dissimilarity Index

$$D = \frac{1}{2} \sum_{i=1}^{n} \left| \frac{g_i}{G} - \frac{m_i}{M} \right|$$

Isolation Index

$$P^* = \sum_{i=1}^{n} \left[ \frac{g_i}{G} \cdot \frac{g_i}{t_i} \right]$$

Transit Accessibility (SDG 11.2.1)

$$A(c) = \sum_{s \in S(c, r)} f(s) \cdot e^{-\lambda \cdot d(c, s)}$$

Default: $r = 800$ m, $\lambda = 0.003$.

Land Consumption Rate (SDG 11.3.1)

$$\mathrm{SDG}_{11.3.1} = \frac{\mathrm{LCR}}{\mathrm{PGR}}$$

$$\mathrm{LCR} = \frac{\ln(U_{\mathrm{land}}(t_1) / U_{\mathrm{land}}(t_0))}{t_1 - t_0}$$

$$\mathrm{PGR} = \frac{\ln(P(t_1) / P(t_0))}{t_1 - t_0}$$

Sustainable urban growth: ratio approximately 1. Ratio $> 1$: land consumption outpacing population growth. Ratio $< 1$: increasing density.

Formula Summary Table

Formula Parameters Default
RRF k 60
Transit accessibility r (radius), λ (decay) 800 m, 0.003
URCS physical α_s, α_a, α_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

API Summary

Intent Parsing

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, ...

Spectral Indices

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)

Urban Resilience

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
)

SDG 11 Indicators

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
)

Pilot Configuration

from citysense.pilot import get_pilot_config

config = get_pilot_config("fi")
# config.country, config.national_crs, config.default_cities, ...

Data Sources and Connectors

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

Connector Priority

Pilot configurations define connector_priority to resolve conflicts when multiple sources provide overlapping data.


WUF13 Alignment

The 13th World Urban Forum (WUF13) dialogue dimensions inform CitySense pilot configurations and indicator coverage.

WUF13 Dialogue Dimensions

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

Pilot-Specific Data Gaps

Country Known Gaps Fallback Strategy
Azerbaijan Peri-urban tenure SAR texture + NDBI heuristic for informality
Finland Informal settlements Not applicable; use tenure from registers
Sweden (Per national profile) (Per national profile)
Denmark (Per national profile) (Per national profile)
Norway (Per national profile) (Per national profile)

SpatialIntent Structure

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)

H3 Spatial Index

CitySense uses Uber H3 for hexagonal spatial indexing. Benefits include uniform cell size, hierarchical resolution, and efficient neighborhood queries.

Resolution Reference

Resolution Avg hexagon area (km²) 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

Antimeridian Handling

H3 cells crossing the antimeridian require special handling. CitySense pre-filters queries to avoid invalid geometries.


Dependencies

Core Dependencies

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, <3.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, <6.0 Cloud-optimized GeoTIFF
httpx >=0.28.0, <1.0 HTTP client
Pillow >=11.1.0, <12.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

Optional Dependencies

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

Data Flow

Index Build Flow

OSM Overpass / STAC / Connectors
        │
        ▼
Geometry + Metadata (GeoDataFrame)
        │
        ▼
H3 Cell Assignment (resolution 7 default)
        │
        ▼
Chunking + Text Serialization
        │
        ▼
Dense Embedding (fastembed) + Sparse (BM25)
        │
        ▼
Qdrant Upsert (vectors + payload)

Query Flow

Natural Language Query
        │
        ▼
parse_intent() → SpatialIntent
        │
        ▼
H3 Filter (bbox → H3 cells)
        │
        ▼
Dense + Sparse Retrieval (top-k each)
        │
        ▼
RRF Fusion (k=60)
        │
        ▼
Reranker (optional)
        │
        ▼
Assembled Context (GeoJSON, summary)

Troubleshooting

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

Glossary

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)

Frequently Asked Questions

Is CitySense suitable for production use?

CitySense is in Alpha (Development Status 3). Use for research, prototyping, and pilot deployments. Production hardening is ongoing.

Which embedding model is used?

Default: BAAI/bge-m3. Configurable via CITYSENSE_EMBEDDING_MODEL.

Does CitySense support private repositories?

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.).

How is coverage computed?

Coverage excludes connectors and modules under active development. Run pytest tests/unit --cov=citysense --cov-report=term-missing for current metrics.

Can I add a new pilot country?

Yes. Implement a PilotConfig in citysense.pilot, register in the pilot registry, and add to the CLI init options. See CONTRIBUTING.md.


Version History

Version Date Highlights
0.2.0 2026-02-28 WUF13 alignment, five pilot countries, SDG 11 indicators, mathematical foundations
Unreleased - License EUPL-1.2, initial structure per Specification v0.2.0

Development

Setup

git clone https://github.com/olaflaitinen/citysense.git
cd citysense
pip install -e ".[dev,clip]"
pre-commit install

Linting and Type Checking

ruff check src tests
ruff format --check src tests
mypy src/citysense

Tests

pytest tests/unit -v
pytest tests/unit -v --cov=citysense --cov-report=term-missing

Documentation

mkdocs serve

Priority Contribution Areas

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 Version Compatibility

Python Status
3.12 Supported, tested in CI
3.13 Supported, tested in CI
3.11 Not supported (requires 3.12+)

Commit Message Format

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

Security Considerations

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

Performance Notes

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

References

Spectral Indices

  • 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.

SDG and Urban Indicators

  • 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.

Retrieval

  • Cormack, G. V., Clarke, C. L., & Buettcher, S. (2009). Reciprocal rank fusion outperforms condorcet and individual rank learning methods. SIGIR 2009.

Citation

If you use CitySense in academic work, please cite:

CitySense: Geospatial RAG and MCP Server for Urban AI Development.
Specification v0.2.0. WUF13 Aligned. 2026.
https://github.com/olaflaitinen/citysense

Spectral Index Interpretation Ranges

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

License

EUPL-1.2. See LICENSE.


Links

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

Acknowledgments

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.


Document Conventions

Convention Usage
LaTeX Mathematical formulas use $...$ (inline) and $$...$$ (block). Renders on Read the Docs.
Code blocks Bash for CLI; Python for API examples.
Tables Markdown tables for structured reference data.
Links Relative for in-repo; absolute for external.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

citysense-0.2.0.tar.gz (75.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

citysense-0.2.0-py3-none-any.whl (59.9 kB view details)

Uploaded Python 3

File details

Details for the file citysense-0.2.0.tar.gz.

File metadata

  • Download URL: citysense-0.2.0.tar.gz
  • Upload date:
  • Size: 75.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for citysense-0.2.0.tar.gz
Algorithm Hash digest
SHA256 bd087cd5f532ca9a810d7bcf6ac0ec17d10086b6c9ae6a93229532f24fe03882
MD5 93ec0c50d0ebe313b3f02454ef4669ec
BLAKE2b-256 6f8510a9a0760356f530cf2fa22d8ea9340df22831b7df62df658db385fda4ae

See more details on using hashes here.

File details

Details for the file citysense-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: citysense-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 59.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for citysense-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 375a63790e75c72e2f4b8b89d413fc9f40865ddb39e28d2545e87d557d70a1ab
MD5 39629121e379fb0187a5a41d96b783b9
BLAKE2b-256 6ef86433fcea1f98b57fbd727884a80771065e12b87294eb7e034de782319a6b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page