Skip to main content
Glama

Open Reach

An MCP server for out-of-home (OOH) site-reachability tooling.

Open Reach exposes geospatial reachability and catchment-scoring tools for billboard / ad-site evaluation — isochrone catchments, POI-density scoring, and multi-site comparison — to any MCP client (Claude Desktop, Cursor, etc.), built entirely on open geospatial data and public urban-analytics methodology.

The differentiator is server-side reach scoring and multi-site ranking (site_reach_score, compare_sites). There are several public OSM-wrapper MCP servers already; none of them do catchment scoring. That gap — plus honest, public methodology — is the point of this project.


The hook (demo)

You (in Claude Desktop):
  "I'm scouting 3 candidate billboard sites near KLCC, Bukit Bintang, and
   Mont Kiara. Which has the best pedestrian catchment and highest POI
   density within a 10-minute walk?"

Claude:
  → geocode("KLCC"), geocode("Bukit Bintang"), geocode("Mont Kiara")
  → isochrone(..., mode="walk", minutes=10)            [x3]
  → catchment_pois(..., categories=["cafe","retail","transit"])  [x3]
  → site_reach_score(...)                               [x3]
  → compare_sites(sites=[...], minutes=10, mode="walk")
  ← ranked: 1. Bukit Bintang  2. KLCC  3. Mont Kiara  (with per-site breakdown)

The ranking arithmetic runs server-side in compare_sites — the model's job is orchestration and narration, not the math.


Related MCP server: @nor-data/nabolag-mcp

How it works

  ┌─────────────────────┐   MCP (JSON-RPC over stdio)
  │   MCP Client        │ ──────────────────────────────┐
  │ (Claude Desktop /    │                               │
  │  Cursor / Code)      │ ◄── tool schemas advertised  │
  └─────────────────────┘                               ▼
                                ┌────────────────────────────────────┐
                                │       Open Reach MCP Server         │
                                │          (FastMCP process)          │
                                │                                      │
                                │  @mcp.tool: geocode                  │
                                │  @mcp.tool: reverse_geocode          │
                                │  @mcp.tool: isochrone                │
                                │  @mcp.tool: catchment_pois           │
                                │  @mcp.tool: site_reach_score  ★      │
                                │  @mcp.tool: compare_sites     ★      │
                                │                                      │
                                │  TTL cache + per-host rate limiting  │
                                └──────────────────┬───────────────────┘
                                                   │ https GET/POST
                ┌──────────────────────────────────┼───────────────────────┐
                ▼                                  ▼                       ▼
      ┌───────────────────┐         ┌──────────────────────┐   ┌───────────────────┐
      │ OSM Nominatim     │         │ Overpass API         │   │ OSRM              │
      │ (geocoding)       │         │ (POIs by category)   │   │ (isochrones)      │
      └───────────────────┘         └──────────────────────┘   └───────────────────┘

Each scoring tool chains isochrone → POIs/junctions → a pure, unit-tested arithmetic module, then returns a typed result plus an auditable breakdown.


Tools

Tool

Description

Units

geocode(query)

Forward geocode a place name.

lat/lon decimal degrees

reverse_geocode(lat, lon)

Coordinate → address string.

decimal degrees → string

isochrone(lat, lon, mode, minutes)

Reachable-area polygon within a time budget.

minutes; polygon [lon,lat]; area m²

catchment_pois(lat, lon, minutes, mode, categories)

POIs in the catchment, grouped by enum category.

counts

site_reach_score(lat, lon, minutes, mode, weights?)

Composite reach score [0,1] + breakdown. ★

unitless [0,1]

compare_sites(sites, minutes, mode, weights?)

Deterministic multi-site ranking. ★

ranks (1 = best)

mode{walk, drive, transit}. categories are enum-constrained — callers never supply raw Overpass QL; all queries are built server-side.


Quick start

git clone https://github.com/kasturi/open-reach-mcp.git
cd open-reach-mcp
python -m venv .venv && .venv\Scripts\activate     # Windows
# source .venv/bin/activate                        # macOS/Linux
pip install -e ".[dev]"

Run standalone (stdio):

open-reach-mcp            # or: python -m open_reach_mcp

Claude Desktop config

Add to claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "open-reach": {
      "command": "C:\\path\\to\\open-reach-mcp\\.venv\\Scripts\\open-reach-mcp.exe",
      "args": []
    }
  }
}

Set USER_AGENT (see .env.example) to a descriptive value — Nominatim usage policy requires it.

Tests

pytest --cov=open_reach_mcp --cov-report=term-missing

Methodology & IP boundary (important)

The reach-scoring formula in site_reach_score is derived only from public urban-analytics literature, not from any proprietary methodology or real campaign/device data:

  • Gravity-model catchment accessibility (Hansen, 1959; classic spatial interaction) — each POI contributes exp(-d / D) where d is its distance from the site and D a pedestrian decay constant.

  • Walkability-style density indices — POI density and road-junction density per km², normalized against public reference benchmarks to [0, 1].

  • Category-mix diversity via normalized Shannon entropy.

This project stands for the engineering pattern (geospatial proxy scoring under rate-limited free APIs, packaged as an MCP server). It is not a claim of parity with any production reach/audience system, and it uses no proprietary formulas or real client data.


Upstream dependencies & limits

All upstream APIs are free-tier and shared/public, so they are rate-limited and occasionally fragile. Open Reach mitigates this with:

  • TTL cache (CACHE_TTL_SECONDS, default 24h) + per-host rate limiting (RATE_LIMIT_MIN_INTERVAL_SECONDS, default 1s — Nominatim's policy ceiling).

  • A compliant User-Agent header (configurable; required by Nominatim).

  • transit mode falls back to the OSRM foot profile — OSRM has no transit router. For real transit isochrones, self-host a transit router (e.g. RAPTOR/OTP) and point OSRM_BASE_URL at it. This is a known limitation, stated openly rather than hidden.

  • For production throughput, self-host Nominatim / Overpass / OSRM (Docker images exist for all three) and set the *_BASE_URL env vars. Turning upstream fragility into a documented self-host path is part of the point.


Configuration

All settings are environment-driven (see .env.example):

Variable

Default

Purpose

NOMINATIM_BASE_URL

https://nominatim.openstreetmap.org

Geocoding upstream

OVERPASS_BASE_URL

https://overpass-api.de

POI upstream

OSRM_BASE_URL

https://router.project-osrm.org

Routing upstream

USER_AGENT

open-reach-mcp/0.1.0 (...)

Required by Nominatim policy

CACHE_MAXSIZE / CACHE_TTL_SECONDS

2048 / 86400

TTL cache sizing

RATE_LIMIT_MIN_INTERVAL_SECONDS

1.0

Per-host request spacing

HTTP_TIMEOUT_SECONDS

15.0

Upstream call timeout


Publishing

v1 ships stdio transport. Publishing steps (run manually after build):

  1. PyPI: python -m build && twine upload dist/*.

  2. Official MCP registry: submit server.json (verified GitHub ownership) at registry.modelcontextprotocol.io. PyPI alone no longer supports a "published to the registry" claim; the official registry (launched Sept 2025) requires the manifest + verified ownership.

SSE-only transports are deprecated since MCP spec 2025-03-26. A Streamable HTTP transport is the planned v2 stretch (no SSE).


License

MIT — see LICENSE.

Install Server
A
license - permissive license
A
quality
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    A comprehensive MCP server providing 30 tools for geocoding, routing, and OpenStreetMap data analysis. It enables AI assistants to search for locations, calculate travel routes, and perform quality assurance checks on map data.
    Last updated
    30
    2
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    MCP server for geocoding and place discovery using OpenStreetMap data via Nominatim. Supports forward/reverse geocoding, bounding boxes, nearby places, batch geocoding, route waypoints, and administrative boundaries.
    Last updated
    10
    Apache 2.0

View all related MCP servers

Related MCP Connectors

  • MCP server providing access to the Scorecard API to evaluate and optimize LLM systems.

  • MCP server for Mireye Earth — federal-source-cited geospatial data for any MCP-aware agent.

  • Geo-based flight search MCP server. Find more flights between any two places on earth

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/abangbroy/ooh_reach_mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server