One place-search interface for every AI and map provider. MCP + REST + SDK, provider fallback, merge+dedup, zero API key needed.
claude mcp add geowire -- npx -y @geowirehq/cli{
"mcpServers": {
"geowire": {
"command": "npx",
"args": ["-y", "@geowirehq/cli"]
}
}
}Resumen de MCP Servers
# GeoWire
> **Add real-world places to any AI agent in 5 minutes — no API key required.**
>
> One place-search interface for every AI and map provider.
<p align="center">
<img src="docs/media/geowire-mcp.gif" alt="geowire MCP server — tools/list and a geocode_address call over stdio" width="760">
</p>
GeoWire is an open-source geo search gateway that sits between AI agents and
map/place data providers (OpenStreetMap, Google, your own data) and exposes them
through a single **MCP server**, **REST API**, and **SDK** — with provider
fallback, multi-provider merge + dedup, cost budgets, and a policy engine that
enforces each provider's caching/attribution terms.
**Status: v0.1 ("It works") — published on npm. MCP · REST · CLI · SDK all functional.**
> **Honest by design:** OpenStreetMap (the zero-key default) is a great
> *geocoder* — strong on place names, addresses, and landmarks — but thin on
> category words ("coffee", "pharmacy"), opening hours, and coverage outside
> Europe. Add a Google key for full business data; GeoWire merges both and tells
> you which source every field came from.
**Contents:** [Why](#why-geowire) · [Quickstart](#quickstart) · [MCP tools](#mcp-tools) · [REST](#rest-endpoints) · [Anatomy of a response](#anatomy-of-a-response) · [Config](#configuration-optional--everything-works-without-it) · [Providers](#providers) · [Recipes & examples](#recipes--examples) · [Roadmap](#roadmap) · [Architecture](#architecture)
## Why GeoWire?
| | Direct integration | Single-provider MCP | **GeoWire** |
|---|---|---|---|
| Unified place schema | ❌ per-provider code | ❌ | ✅ |
| Provider fallback on failure | ❌ | ❌ | ✅ |
| Multi-provider merge + dedup | ❌ | ❌ | ✅ |
| Cost budgets & routing | ❌ | ❌ | ✅ |
| Works without any API key | ❌ | depends | ✅ (OSM by default) |
| Self-hosted | — | depends | ✅ |
| Your own place data as a provider | ❌ | ❌ | ✅ |
| Transparent provenance (which source, what cost) | ❌ | ❌ | ✅ (every response) |
**Not a Google replacement — it *uses* Google.** The thing no single provider can
do: merge **your own store data + Google + OSM** into one deduped record, with
per-field provenance (your name is authoritative, Google adds ratings, OSM adds
coordinates). Real run below:
<p align="center">
<img src="docs/media/geowire-merge.gif" alt="GeoWire merging a private store DB, Google, and OpenStreetMap into one record with per-field provenance" width="760">
</p>
## Quickstart
### 1. MCP (Claude Desktop / Cursor) — 30 seconds
Add this to your MCP client config (e.g. Claude Desktop `claude_desktop_config.json`):
```json
{
"mcpServers": {
"geowire": { "command": "npx", "args": ["-y", "@geowirehq/mcp"] }
}
}
```
Then ask: *"Where is the Eiffel Tower?"* or *"Find a Starbucks within 3 km of
37.4979, 127.0276."* Works with **zero API keys** — OpenStreetMap is the default.
Add `"env": { "GOOGLE_MAPS_API_KEY": "..." }` for business listings and hours
(e.g. *"Find a 24-hour pharmacy near me"*). See [more MCP client configs](./examples/mcp-clients.md).
### 2. CLI — one-shot search & server
<p align="center">
<img src="docs/media/geowire-search.gif" alt="geowire search in the terminal, with source attribution and response time" width="720">
</p>
```bash
npx @geowirehq/cli search "Eiffel Tower" # terminal search with a results table
npx @geowirehq/cli search "Starbucks" --near 37.4979,127.0276 --radius 3000 # near a coordinate
npx @geowirehq/cli reverse 37.5665,126.9780 # coordinate → nearest place
npx @geowirehq/cli route 37.5665,126.9780 37.4979,127.0276 # driving directions (no key, OSRM)
npx @geowirehq/cli get google:ChIJ... # one place by reference (getPlace-capable provider)
npx @geowirehq/cli # start the REST + MCP server (zero-config)
npx @geowirehq/cli init # interactive setup wizard (.env + config)
npx @geowirehq/cli test # check provider connections
```
Add `--json` to any command for the full response (results + provenance `meta`).
### 3. Docker — self-hosted server
```bash
docker run -p 4980:4980 geowire/geowire
# then:
curl -X POST http://localhost:4980/v1/places/search \
-H 'content-type: application/json' \
-d '{"query":"Starbucks","near":{"latitude":37.4979,"longitude":127.0276},"radiusMeters":3000}'
```
Or with `docker compose up` (see `docker-compose.yml`). API docs at `/docs`.
### 4. SDK (embedded)
```ts
import { createGeoWire } from "@geowirehq/core";
import { createNominatimProvider } from "@geowirehq/provider-nominatim";
const geo = createGeoWire({ providers: [createNominatimProvider()] });
const { results, meta } = await geo.searchPlaces({
query: "Starbucks",
near: { latitude: 37.4979, longitude: 127.0276 },
radiusMeters: 3000,
});
```
Full embedded-SDK guide: [`examples/typescript-sdk.md`](./examples/typescript-sdk.md).
## MCP tools
| Tool | Description |
|---|---|
| `search_places` | Natural-language + coordinate/region place search |
| `get_place` | Details by `provider:providerPlaceId` reference |
| `geocode_address` | Address → coordinates (+ normalized address) |
| `reverse_geocode` | Coordinates → nearest address |
| `get_directions` | Route between waypoints (distance, time, legs) — no key (OSRM) |
| `distance_matrix` | N×M travel distances/times — rank candidates by drive time — no key |
| `analyze_area` | Commercial-area analysis: category density, competition, rating landscape |
| `list_geo_providers` | Active providers, capabilities, status (agent self-awareness) |
Every response includes both a human-readable summary and `structuredContent`
(schema-valid JSON).
## REST endpoints
| Method | Path | |
|---|---|---|
| POST | `/v1/places/search` | search |
| GET | `/v1/places/{ref}` | place details (`provider:id`) |
| GET | `/v1/geocode?address=` | geocode |
| GET | `/v1/reverse-geocode?lat=&lon=` | reverse geocode |
| POST | `/v1/directions` | directions between waypoints (no key) |
| POST | `/v1/distance-matrix` | N×M travel distance/time matrix (no key) |
| POST | `/v1/analyze-area` | commercial-area analysis (density, competition, ratings) |
| GET | `/v1/providers` | list providers |
| GET | `/v1/health` | health check |
| GET | `/metrics` | Prometheus metrics |
| GET | `/docs` | Swagger UI (OpenAPI 3.1) |
| POST | `/mcp` | MCP over Streamable HTTP |
Optional Bearer auth: set `GEOWIRE_API_KEYS=key1,key2`.
## Anatomy of a response
No black box. Every response carries a `meta` block: which providers were
**used / skipped / failed** (and why), dedup counts, cache status, estimated
cost, and per-field sourcing — so you always know where each value came from.
```jsonc
{
"results": [{
"id": "gwp_CvWvRZrFtegkJPxP9CW0",
"name": "경복궁",
"location": { "latitude": 37.579754, "longitude": 126.9766818 },
"sources": [{
"provider": "nominatim",
"providerPlaceId": "relation/5501517",
"fields": ["name", "location", "categories", "address"] // ← what this source contributed
}],
"attributions": ["© OpenStreetMap contributors"]
}],
"meta": {
"providersUsed": [{ "provider": "nominatim", "resultCount": 1, "latencyMs": 2449 }],
"providersSkipped": [], // e.g. { provider: "google", reason: "MISSING_CREDENTIALS" | "QUOTA_EXCEEDED" }
"providersFailed": [], // e.g. { provider: "google", reason: "TIMEOUT" }
"strategy": "first-success",
"cache": { "hit": false }
// merging adds: "dedup": { "before": 3, "after": 1 }
// paid provider: "estimatedCostUSD": 0.032
}
}
```
After a merge, `sources[].fields` shows (say) the phone came from Google while
the coordinates came from OSM. Walkthrough: [docs/recipes.md](./docs/recipes.md#4-read-a-response-provenance--transparency).
## Configuration (optional — everything works without it)
`geowire.config.yaml`:
```yaml
providers:
nominatim: { enabled: true } # default ON, no key
google: { enabled: true, apiKey: ${GOOGLE_MAPS_API_KEY} }
kakao: { enabled: true } # env KAKAO_REST_API_KEY (KR)
naver: { enabled: true } # env NAVER_CLIENT_ID + NAVER_CLIENT_SECRET (KR)
internal: { enabled: true, source: ./my-places.csv, priority: 100 }
routing:
defaultStrategy: merge # first-success | merge | cost-aware | weighted | fastest
providerWeights: # for `weighted`: order by priority·cost·coverage
priority: 0.5
cost: 0.3
coverage: 0.2
budget:
perRequestMaxUSD: 0.10 # over-budget paid providers are skipped, free ones used
```
Keys come from the environment (`${VAR}`), never committed in plaintext.
## Providers
| Provider | Key? | Capabilities |
|---|---|---|
| `@geowirehq/provider-nominatim` (OpenStreetMap) | none | search, geocode, reverseGeocode |
| `@geowirehq/provider-osrm` (OpenStreetMap routing) | none | route, distanceMatrix |
| `@geowirehq/provider-google` (Maps Platform) | BYOK | search, geocode, reverseGeocode, getPlace, route, distanceMatrix |
| `@geowirehq/provider-kakao` (카카오맵, KR) | BYOK `KAKAO_REST_API_KEY` | search, geocode, reverseGeocode |
| `@geowirehq/provider-naver` (네이버 지역검색, KR) | BYOK `NAVER_CLIENT_ID`+`NAVER_CLIENT_SECRET` | search, geocode |
| `@geowirehq/provider-baidu` (百度地图, CN) | BYOK `BAIDU_MAP_AK` | search, geocode, reverseGeocode |
| `@geowirehq/provider-foursquare` (global POI) | BYOK `FOURSQUARE_API_KEY` | search, getPlace |
| `@geowirehq/provider-internal` (your CSV) | none | search |
Regional providers make Korea (Kakao/Naver) and China (Baidu) coverage
first-class where OSM is thin and Google has gaps — Baidu returns BD-09
coordinates, which GeoWire converts to WGS84 automatically. Merge them all +
your own store data into one deduped record.
### Provider roles — each provider does what it's best at
Providers aren't interchangeable; they're **complementary**. When `merge` combines
duplicates, GeoWire doesn't just pick the highest-priorLo que la gente pregunta sobre geowire
¿Qué es geowire/geowire?
+
geowire/geowire es mcp servers para el ecosistema de Claude AI. One place-search interface for every AI and map provider. MCP + REST + SDK, provider fallback, merge+dedup, zero API key needed. Tiene 0 estrellas en GitHub y se actualizó por última vez today.
¿Cómo se instala geowire?
+
Puedes instalar geowire clonando el repositorio (https://github.com/geowire/geowire) o siguiendo las instrucciones del README en GitHub. ClaudeWave también te ofrece bloques de instalación rápida en esta misma página.
¿Es seguro usar geowire/geowire?
+
geowire/geowire aún no ha sido auditado por nuestro agente de seguridad. Revisa el repositorio original en GitHub antes de usarlo en producción.
¿Quién mantiene geowire/geowire?
+
geowire/geowire es mantenido por geowire. La última actividad registrada en GitHub es de today, con 21 issues abiertos.
¿Hay alternativas a geowire?
+
Sí. En ClaudeWave puedes explorar mcp servers similares en /categories/mcp, ordenados por popularidad o actividad reciente.
Despliega geowire en tu cloud
Lleva este repo a producción en minutos. Cada plataforma genera su propio entorno con variables de entorno editables.
¿Mantienes este repo? Añade un badge a tu README
Pega el badge en tu README de GitHub para mostrar que está auditado por ClaudeWave. Cada badge enlaza de vuelta a esta página y muestra el Trust Score actual.
[](https://claudewave.com/repo/geowire-geowire)<a href="https://claudewave.com/repo/geowire-geowire"><img src="https://claudewave.com/api/badge/geowire-geowire" alt="Featured on ClaudeWave: geowire/geowire" width="320" height="64" /></a>Más MCP Servers
Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.
User-friendly AI Interface (Supports Ollama, OpenAI API, ...)
An open-source AI agent that brings the power of Gemini directly into your terminal.
The fastest path to AI-powered full stack observability, even for lean teams.
🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl!
Real-time global intelligence dashboard. AI-powered news aggregation, geopolitical monitoring, and infrastructure tracking in a unified situational awareness interface