AtlasFetch vs Offnadir Delta MCP

A side-by-side look at the AtlasFetch and Offnadir Delta MCP MCP servers: transport, auth, tools, quality signals, and the config to install either one in Claude, Cursor, Windsurf or VS Code.

AtlasFetch logoAtlasFetchLocation Services · Local subprocess (stdio)Reverse geocode a coordinate to country, region and municipality, and match your own geofences.61GoodAuth: not declaredOffnadir Delta MCP logoOffnadir Delta MCPLocation Services · Local subprocess (stdio)Live, geolocated world-event intelligence and a Daily World Brief for AI agents — query event signals (coordinates, severity, sources), hotspots, and satellite imagery (Sentinel-1/2 etc), plus an OSINT/GEOINT analyst. Streamable HTTP + OAuth; free tier, token-metered.64GoodAuth: other

Verdict: choose AtlasFetch for location services work as a local process; choose Offnadir Delta MCP for location services as a local process. You can also run both side by side in one mcpServers block.

Which MCP server should you choose?

AtlasFetch logoChoose AtlasFetch when

  • You need dedicated capabilities in the Location Services domain.
  • You prefer a local stdio subprocess transport.
  • You have the keys it needs: ATLASFETCH_API_KEY, ATLASFETCH_API_URL.
  • You want tools like lookup_location, geocode_address, list_boundary_sets.
Explore AtlasFetch

Offnadir Delta MCP logoChoose Offnadir Delta MCP when

  • You need dedicated capabilities in the Location Services domain.
  • You prefer a local stdio subprocess transport.
  • Its auth model fits you: other.
  • You have the keys it needs: OFFNADIR_DELTA_API_KEY.
  • You want tools like query_signals, query_stats, query_hotspots.
Explore Offnadir Delta MCP

Feature & specification comparison

Rows where the two servers differ are marked.

SpecAtlasFetch logoAtlasFetchOffnadir Delta MCP logoOffnadir Delta MCP
CategoryLocation ServicesLocation Services
Quality signal61/100 · Good64/100 · Good
Install commandConfirmedConfirmed
TransportLocal subprocess (stdio)Local subprocess (stdio)
AuthNot declaredother
PricingNot declaredFreemium
Required env varsATLASFETCH_API_KEYATLASFETCH_API_URLOFFNADIR_DELTA_API_KEY
Verified ownerCommunity listingCommunity listing
GitHub stars00
Directory activity 1 views 0 installs 0 upvotes 4 views 0 installs 0 upvotes
Tools740

Tools & capabilities

AtlasFetch tools 7

  • lookup_locationReverse geocode a coordinate to the administrative areas that contain it — country, region (state or province) and municipality — as names plus ISO 3166 codes, optionally the nearest street, and matches from boundary sets the account has uploaded: all in one call. Use for: which country, region or municipality a point is in; which street a point is on (add "street" to base); geofence checks against your own polygons; tagging data with region codes. For the other direction, an address to a coordinate, use geocode_address. For a route, a travel distance or a travel time, use get_route — 10 lookups on the standard plans to this one’s 1. Do NOT use for place search by name or for fetching boundary geometry. Caveats worth repeating to the user: municipal is the finest unit AVAILABLE, not a consistent kind of thing — Los Angeles returns a city, rural Kansas returns a county, so do not assume it names a city. A layer that matched nothing comes back null. The errors array is always present: a boundary set that is unavailable or not granted to this key is skipped and reported there, while the call itself still succeeds. STREETS (opt-in via base, worldwide). base.street is ALWAYS three answers, for 5 m, 20 m and unlimited in that order, each with radiusMeters, streetNumber, streetName, postcode and distanceMeters. A numbered address within the radius wins over a nearer street (for the unlimited entry the address must still be within 20 m); otherwise the nearest named street; unnamed roads never answer. Two different nulls: base.street === null means there is no street data for the point’s country, while an entry whose fields are null means nothing was within that radius — never report them the same way. streetNumber and postcode are STRINGS (44A, 12-14, 0181), house numbers are rare outside well-mapped areas. Street geometry comes back only when streetGeometry is set — leave it off unless something will draw the line. One call is one billed lookup however many layers, sets or grid codes it touches, and a call that matches nothing still bills.
  • geocode_addressTurn ONE address into a point, with an honest account of how much of it was found. Built for deliveries. South Africa today; more countries as their data loads. 1 lookup per address, found or not. Send either q (one line) or address (housenumber, street, suburb, city, postcode, unit) — never both. If the address is already split, send it split: it matches better. READ precision BEFORE using the point. "address" means the house was found; "interpolated" means it was estimated between the numbers either side; "intersection" means a street corner ("Cnr Main Rd and Belmont Rd", "Bree & Strand Streets"), at the point where the two meet, with the second street in matched.crossStreet; "site" means a named site — a shopping centre, office park, complex or estate, hospital, school, airport or hotel — at a point inside it, named in matched.site; "street" means the right street but NOT the house; "locality" means only the suburb or town. NEVER present a street- or locality-level point as a door: a driver sent there will be at the wrong house. In South Africa most answers are street-level, because OpenStreetMap has house numbers on about 13% of street names — that is the data being honest, not a failure. What to do with an answer — the result line says which applies: - address, interpolated, intersection or site, not ambiguous, confidence 0.5 or more: dispatch. For a site, pass on the unit or shop number from the original address ("Shop 12") — the answer does not include it, and the driver needs it. - street: ask the recipient for a pin or a landmark. - ambiguous, or locality: ask the customer before dispatching. When the advice is to ask the customer, ASK — do not pick one. result.alternatives holds up to 4 other candidates the answer was chosen from, and the result line lists them with their distance and direction from the first, because they often share a street name AND a town (five "Long Street, Cape Town"s). Put the first answer and those to the user. Free: still one lookup. confidence ranks answers; it is NOT a probability. ambiguous means a same-named street elsewhere scored about as well, or the street was a near-miss spelling with no house number to confirm it. result null means nothing trustworthy was found, and that still costs the lookup. Some addresses name something that cannot be placed: an erf, stand, plot or farm portion (land parcels — there is no cadastre), a township stand, a PO box or private bag. Those parts come back in unmatched and the answer is the place named, at locality: ask the customer for a street address. country is a hard filter; region (ZA-WC, or "Western Cape") only ranks streets inside it first, so a wrong province does not lose the address. An uncovered country is refused, unbilled, with the list of covered countries in the message — that message is the live coverage list; there is no other. sets and base answer "which delivery zone is it in" in the same call, at no extra cost. One address per call, deliberately. For a delivery list, call this once per row so the user sees what is being spent; programs with thousands of rows should use the API’s POST /geocode/batch directly. Not for: searching for a business or landmark by name, or a coordinate to an address (that is lookup_location with the street layer).
  • list_boundary_setsLists the boundary sets on this account with their boundary counts and the API keys (id and label) each is granted to. A set only matches during a lookup when it is available AND granted to the key making the call. On the shared demo key, grantedKeys is always empty.
  • create_boundary_setCreates an empty named set to hold your own polygons: delivery zones, service areas, sales territories. IMPORTANT, and not a bug: a new set is created unavailable and granted to no key, so it matches nothing until both are changed. Granting is addressed by API key id, and nothing this server can call tells it its own key's id. So this tool can create the set and add boundaries to it, but the FIRST grant has to happen in the dashboard: tell the user to switch the set on and grant it to the key this server uses, at https://atlasfetch.xyz/dashboard.
  • add_boundaryAdds ONE polygon to an existing boundary set on this account, so that lookup_location reports when a point falls inside it — delivery zones, service areas, sales territories. Each call creates a new boundary: calling twice with the same name stores two. Before calling: the set must already exist (create_boundary_set). A set matches nothing in lookups until it is switched on and granted to an API key in the dashboard at https://atlasfetch.xyz/dashboard, which this server cannot do. geometry must be a single GeoJSON Polygon — not a MultiPolygon, Feature or FeatureCollection. Positions are [longitude, latitude]. Each ring needs at least 4 positions and must be closed (last position equals the first); extra rings are holes. Self-intersecting shapes are rejected. To store a MultiPolygon, add each part separately. A polygon may have at most 50 points on EVERY plan, the closing one included; more is refused, unbilled, with advice to simplify the shape or split it into several boundaries. Plan limits cap properties per boundary and boundaries per set. WITHOUT YOUR OWN KEY, the shared demo key is on the Public plan: properties only category (zone, area, route, place, other), color (green, blue, red, yellow, purple, orange) and priority (low, medium, high), and one set shared with every demo user, where adding to a full set silently deletes its oldest boundary. Never upload anything private with the demo key. Returns the stored boundary: id, set, name, properties, pointCount and createdAt.
  • update_boundaryReplace the shape of ONE existing boundary. Its id, name, properties and set stay as they are, so every lookup that matches it keeps returning the same properties. Use this to fix or move a zone. Do NOT delete it and add it again: that gives it a new id and loses the properties unless they are re-sent. Name the boundary by set and name; this finds its id. If a set holds two boundaries with that name, the answer lists their ids and asks for one. The new shape gets the same checks as add_boundary, including the 50-point cap (refused, unbilled). Only boundaries on this account can be changed.
  • get_routeA driving, cycling, walking or truck route from the first location to the last, via any in between, with distance, duration and turn-by-turn steps. COST: a route is 10 LOOKUPS on the standard plans, not one (a custom plan may charge less; X-Lookups-Remaining is always the truth). Everything it returns is included in that, so do not call it in a loop to compare options without saying so. Durations are FREE-FLOW: the road network at its own speed limits, with NO live or historical traffic. Never present one as an arrival time in traffic — for that, say a traffic-aware service (Google, Mapbox) is needed. The route line is NOT returned unless routeGeometry is set, because an encoded polyline is thousands of characters that no one reads. Ask for it only when something will draw it. Locations are SNAPPED to the nearest routable road, and locations[] in the response says how far each one moved. A large snapDistanceMeters means the answer starts somewhere else than asked — worth repeating to the user. avoidSets and exposureSets name BOUNDARY SETS on the account (list_boundary_sets), not ad-hoc shapes. avoid routes around every zone in those sets; exposure leaves the route alone and reports how far it ran inside each zone. A zone containing one of the locations cannot be avoided for that route: it is skipped and reported in avoid.skipped. Along very many exposure zones (over 1,000, or over 5 s to measure) exposure is skipped: it comes back empty with a note in errors, and the route is still answered and billed. TRUCKS (Pro only): a truck over 9 t, or with no weightTonnes, is capped at 80 km/h, as South African law caps goods vehicles; a lighter truck keeps car speeds. The vehicle’s height, width, length, weight, axle load and hazmat are checked against road limits where OpenStreetMap records them, which is not everywhere — a good start, not a legal clearance. Limits by plan: 2 locations and 1 alternative on the free plans, up to 25 and 2 on Pro; alternatives need exactly 2 locations. Over a cap the answer is 403, and nothing is billed. A location with no road near it, or two places with no road between them, is 422 — and that one IS billed, because the route was attempted. Not for: distance matrices, isochrones or live traffic (none exist yet), and not for which-area-is-this questions — that is lookup_location, at one lookup.

Offnadir Delta MCP tools 40

  • query_signalsGeolocated world events from global news media, AI-enriched with severity/GEOINT scores and collection recommendations.
  • query_statsRoll-ups over the corpus: totals plus per-category and per-day breakdown. `total` counts the same events query_signals returns, so it matches its meta.total_count for the same query.
  • query_hotspotsWhere activity concentrates: density grid-binned into ranked cells with peak severity, categories and representative event_ids. Events too coarse to place are counted in meta.dropped_by_plottable_count, not spread over the grid.
  • get_world_briefAI world brief: daily (prior UTC day, all plans) or weekly/monthly by plan. freshness.is_stale: no newer day, so relay as stale.
  • get_usageThe calling key's remaining token balance and plan capabilities. Pre-flight a metered call with it.
  • search_imagerySearch the imagery catalog over an area and window. Metadata only, no pixels. eventDate tags each scene pre/post — **a same-day scene is same_day_unknown, never post** — and eventPoint/eventAoi add target_relation, so a scene that only clips the bbox is not read as covering the event.
  • plan_event_imageryThe deterministic imagery plan for ONE event: checks BOTH sensors exactly once — sentinel-1-grd (SAR, the only look that survives cloud and night) and sentinel-2-l2a — against the event footprint and a pre/post window. **A VHR recommendation never invalidates what the free catalog showed.**
  • rank_imaging_priorityWHERE, and with what class of satellite, observation is most worthwhile now: composite IMPORTANCE crossed with the SPEC CLASS the required resolution demands — coarse, hr (free Sentinel-class) or vhr. Deterministic.
  • survey_observable_eventsWhich events a sensor can actually RESOLVE, over the FULL set. **The population is ungated by tasking readiness**, so its total sits above rank_imaging_priority and counts a different unit from query_signals clusters.
  • predict_satellite_passesWHEN a place can next be imaged and by WHAT: 13 free-systematic and commercial-taskable families. **Every pass is a GEOMETRIC access opportunity** — no operator plan is consulted. retrieval_ok:false means timing is UNAVAILABLE, never "no passes".
  • assess_signalAI remote-sensing deep-dive for one signal: what to observe, sensors, a collection window. Also returns a deterministic `context` whose `imagery_handoff.parameters` are the exact search_imagery inputs. Cached per signal; not-observable signals are rejected before any charge.
  • ask_analystAsk the Delta Analyst an OSINT/GEOINT question; returns a structured brief. **Durable async**: {status:"processing", job_id} comes back immediately and the run finishes in a background worker. Fetch with get_analyst_job, or re-send the SAME idempotencyKey (no second charge).
  • +28 more on the listing page

Ready-to-paste client configs

Paste either block (or both) into your client config, e.g. claude_desktop_config.json or ~/.cursor/mcp.json. We only show a config when the install command is confirmed.

AtlasFetch

mcpServers (Claude Desktop / Cursor)
{
  "mcpServers": {
    "atlasfetch-2": {
      "command": "npx",
      "args": [
        "-y",
        "atlasfetch-mcp"
      ],
      "env": {
        "ATLASFETCH_API_KEY": "YOUR_ATLASFETCH_API_KEY_HERE",
        "ATLASFETCH_API_URL": "YOUR_ATLASFETCH_API_URL_HERE"
      }
    }
  }
}

Offnadir Delta MCP

mcpServers (Claude Desktop / Cursor)
{
  "mcpServers": {
    "off-nadir-lab-offnadir-delta-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "offnadir-delta-mcp"
      ],
      "env": {
        "OFFNADIR_DELTA_API_KEY": "YOUR_OFFNADIR_DELTA_API_KEY_HERE"
      }
    }
  }
}

Frequently asked questions

AtlasFetch is categorized under Location Services and uses a local stdio subprocess. Offnadir Delta MCP belongs to Location Services and uses a local stdio subprocess. Pick AtlasFetch for location services work and Offnadir Delta MCP for location services.

Copy the mcpServers block from the config section on this page into your client's config (for example claude_desktop_config.json or ~/.cursor/mcp.json), then fully restart the client.

AtlasFetch has no declared pricing — check the project's own site. Offnadir Delta MCP is listed as freemium — a free tier with paid plans. Auth: other. If a server needs environment variables such as API keys, define them under the env key in your client's MCP config.

Yes. MCP clients support multiple servers: add atlasfetch-2 and off-nadir-lab-offnadir-delta-mcp as separate keys in the same mcpServers object, and your assistant will call tools from either one.

On AllMCPs, AtlasFetch has a quality signal of 61/100 (Good) with 1 views, 0 installs and 0 GitHub stars. Offnadir Delta MCP has 64/100 (Good) with 4 views, 0 installs and 0 GitHub stars.