What geog.ai over MCP is
An MCP client (or an agent runtime that speaks MCP) connects once, discovers the tool catalog with a free tools/list call, then calls tools with tools/call. Every tool is a thin, audited wrapper over a registered geog.ai capability — there is no duplicate business logic and the LLM in your agent never invents spatial numbers.
For a human developer: it is the fastest way to give an existing assistant terrain, flood, routing, siting, change-detection, and evidence tools without writing a REST client. For an autonomous agent's operator: the catalog is self-describing — cost, required scope, and sync/async + poll route are all visible from tools/list, so a planner can judge entitlement, budget, and polling before it commits.
- Every result carries
validation,provenance, and atrust_level. - Capability failures come back as MCP tool errors (
isError:true) carrying a machine-readable taxonomy — an agent can tell retryable from terminal without parsing prose. - Async capabilities return a job id; you poll the REST route in each tool's poll column — MCP has no generic job wrapper.
initialize,ping, andtools/listare free and unmetered;tools/callmeters per underlying capability.
Connect
Use a geog.ai API key as a bearer token. The same key's scopes gate which tools can execute (see Scopes).
Claude Code
Terminal
claude mcp add geog-ai --transport http https://api.geog.ai/v1/mcp \ --header "Authorization: Bearer $GEOG_API_KEY"
Claude Desktop / generic MCP client config
JSON config
{
"mcpServers": {
"geog-ai": {
"type": "streamable-http",
"url": "https://api.geog.ai/v1/mcp",
"headers": { "Authorization": "Bearer YOUR_GEOG_API_KEY" }
}
}
}
Raw JSON-RPC (curl)
List tools — free, unmetered
curl -s https://api.geog.ai/v1/mcp \ -H "Authorization: Bearer $GEOG_API_KEY" \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Call a tool — metered per capability
curl -s https://api.geog.ai/v1/mcp \ -H "Authorization: Bearer $GEOG_API_KEY" \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/call", "params":{"name":"get_spatial_context", "arguments":{"device_id":"sensor_h2s_023"}}}'
initialize first (protocol 2025-03-26), then tools/list. Both are free. The server's initialize instructions state the uniform error model once, so it is not repeated in every tool description.Tool catalog
Rendered live from the capability registry (/assets/capabilities.json). Each tool delegates to a deterministic capability. Cost is the metered MCP charge in DC (Decision-Credit units); where the equivalent REST ACU rate differs it is shown in parentheses — see the rate card. Async tools return a job id; poll the capability-specific REST route shown in the Kind column.
Loading tool catalog…
Scopes & the 403 wall
Tool calls enforce capability-aware API-key scopes before anything executes. A read-only key can use every discovery and read tool but receives HTTP 403 (insufficient_scope) the moment it calls a compute-job tool.
| Scope | Unlocks | Example tools |
|---|---|---|
| read | Discovery, context, terrain, routing reads, graph queries, evidence checks | get_spatial_context, find_nearby, calculate_route, check_evidence_at_point |
| simulate | Simulation and multi-step plan execution jobs | simulate_flood, simulate_wildfire_spread, predict_zone_risk, execute_spatial_plan |
| optimize | Placement / coverage optimization jobs | optimize_placement |
| admin | Property-graph entity queries, calibration cycles | query_graph, run_calibration_cycle |
execute_analysis_plan requires every scope its steps need — a plan with a simulation step and an optimization step needs both simulate and optimize. The plan is refused up front if the key is missing any.Error taxonomy & recovery
A failed capability returns a normal MCP result with isError:true. The payload carries a machine-readable code and a boolean retryable flag, so an agent branches on structure, not on message text. The full per-code taxonomy is also available over plain HTTP at GET /v1/capabilities (error_taxonomy).
Transient failures
Retry with exponential backoff; the same call can succeed later.
RATE_LIMITED— you exceeded the request budget; honorRetry-After.DEPENDENCY_UNAVAILABLE— an upstream data source (DEM, STAC, gage) is momentarily down.TIMEOUT— the compute budget elapsed; resubmit, optionally smaller.
Permanent failures
Fix the request or the entitlement — retrying is wasted spend.
insufficient_scope— the key lacks the tool's scope (see above).VALIDATION_ERROR— bad geometry, bbox, or missing argument.NOT_ENTITLED— the tenant is not entitled to the requested data slice.CAPABILITY_UNAVAILABLE— feature requires infra not present (e.g. pgRouting, a live LM backend).
isError:true: read error.code; if error.retryable is true, back off and retry (respecting Retry-After on RATE_LIMITED); otherwise surface the code to the operator and stop — never loop on a terminal error.Readiness, trust & provenance
Every successful tool result ships three honesty fields so an agent can decide how far to trust an answer before it acts on it.
trust_level— a per-result grade that rolls up source quality and degradation. For multi-step plans, per-step trust levels roll up into a plan-leveltrust_level— a plan is only as trustworthy as its weakest step.provenance— the actual data sources used, including whether a real source (e.g. USGS 3DEP DEM, LANDFIRE FBFM40 fuel, Overture GERS entities) or a flagged synthetic fallback answered. Fallbacks are never silent.validation— input and geometry checks that passed, plus any quality gates (e.g. HLS minimum clean-scene count) that were enforced.
check_evidence_at_point ("Why not here?") are labelled estimated / screening-grade and cap at a few DC; they never fabricate a value — an unavailable evidence family reports value=null with an honest reason. A full graded decision comes from create_analysis_plan / /v1/analyze.Async jobs & polling
Simulation, optimization, export, prediction, and calibration tools run as async jobs. The tools/call returns immediately with a job id; MCP itself has no generic job wrapper, so you poll the exact REST route listed in that tool's row — this varies by capability. Simulation and optimization use GET /v1/simulate/jobs/{job_id} (and its /result sub-route); predictions poll GET /v1/predict/zone_risk/{id}; GeoParquet exports poll GET /v1/export/geoparquet/{id} (and /download); calibration follows its admin calibration routes. Always use the poll route shown for the tool you called.
1 — submit (metered once, at submission)
curl -s https://api.geog.ai/v1/mcp \ -H "Authorization: Bearer $GEOG_API_KEY" -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":3,"method":"tools/call", "params":{"name":"simulate_flood", "arguments":{"bbox":[-105.1,39.0,-105.0,39.1],"rainfall_mm":100}}}' # -> result contains a job id, e.g. "job_id":"sim_9f2a"
2 — poll status until terminal
curl -s https://api.geog.ai/v1/simulate/jobs/sim_9f2a \ -H "Authorization: Bearer $GEOG_API_KEY" # status: queued -> running -> succeeded | failed
3 — fetch the result on success
curl -s https://api.geog.ai/v1/simulate/jobs/sim_9f2a/result \ -H "Authorization: Bearer $GEOG_API_KEY"
failed status carries the same error taxonomy as a synchronous isError:true.Metering & what is free
- Free & unmetered:
initialize,ping,tools/list, and the discovery toolslist_capabilitiesanddiscover_spatial_datasets. - Metered: every
tools/callto a compute capability, charged in Decision-Credit (DC) units — the per-capabilitystep_costshown in each tool's Cost column. This can differ from the corresponding REST endpoint's ACU rate (e.g. a flood simulation is 10 DC via MCP vs 80 ACU on REST); where they differ the REST ACU rate is noted alongside. See each tool's row for the exact charge. - Once, at submission: async jobs meter only the submit call; polling and result fetch are free.
MCP charges are in DC (Decision-Credit units); see the rate card for the equivalent REST ACU rates and DC→USD conversion.