MCP server
spatialflow-mcp is a local Model Context Protocol server. It lets an AI assistant such as Claude Desktop, Claude Code or Cursor answer questions about your workspace: where devices are, which geofences they entered, how long a truck sat at a facility, and how workflows ran.
It runs on your computer over stdio and calls the SpatialFlow API with your API key. It only reads: every request is a GET, and no tool creates, changes or deletes anything.
The package is spatialflow-mcp on PyPI and the source is at spatialflow-io/spatialflow-mcp. It needs Python 3.10 or newer. With uv installed, uvx downloads and runs it, so there is nothing else to install.
Create a read-only key
Create a key as described in Authentication and API keys, with these settings:
- Turn on Read-only mode. The API then rejects anything but
GETfor this key, even if a bug or a prompt injection asked for more. - Grant only the permissions for the tools you want:
| Tools | Key permission |
|---|---|
list_devices, get_device, get_recent_locations, list_geofence_events, detention_report, fleet_report | devices:read |
list_geofences | geofences:read |
list_workflows | workflows:read, and the key's owner must be a workspace owner or manager |
list_workflow_executions | workflows:read; a field worker's key sees only runs from their own devices |
A key acts in the workspace it was created in, with its owner's role there. A tool whose permission the key lacks returns a short permission error, and the other tools keep working.
Connect a client
Claude Desktop
Add this to claude_desktop_config.json, then restart Claude Desktop:
{
"mcpServers": {
"spatialflow": {
"command": "uvx",
"args": ["spatialflow-mcp"],
"env": { "SPATIALFLOW_API_KEY": "<your-api-key>" }
}
}
}
Claude Code
claude mcp add spatialflow --env SPATIALFLOW_API_KEY=<your-api-key> -- uvx spatialflow-mcp
Other clients
Any MCP client that starts stdio servers works. Use the command uvx with the argument spatialflow-mcp, and set the environment variables below. If you'd rather not use uv, pip install spatialflow-mcp puts a spatialflow-mcp command on your path.
| Variable | Required | Default |
|---|---|---|
SPATIALFLOW_API_KEY | yes | none |
SPATIALFLOW_API_URL | no | https://api.spatialflow.io |
The server logs to stderr. It never logs the API key or returns it in tool output.
Tools
Every tool is marked read-only for the client. List tools return total_count, returned_count, truncated, a hint for narrowing the query, and items. limit defaults to 100 and is capped at 500.
| Tool | Returns |
|---|---|
list_devices | Devices with status, last location, shift state and the geofences they are inside |
get_device | One device, including its open shift |
get_recent_locations | The newest GPS points for a device |
list_geofences | Geofences without polygon coordinates; filter by tag |
list_geofence_events | Entry and exit events; filter by device, geofence, type and time |
list_workflows | Workflows with status and run statistics |
list_workflow_executions | Workflow runs; filter by workflow and status |
detention_report | One row per facility visit, with time over the free window and the amount owed |
fleet_report | Time on site, trips, idle stops, mileage or attendance (kind) over a date range |
Report dates are YYYY-MM-DD days in the workspace time zone, and the default range is the last 7 days. The tools return report summaries unchanged, and limit caps only the rows. The Reports guide explains what each report counts.
Timestamps are UTC. Distances are in meters and speeds in meters per second.
Detention report
detention_report takes free_time_minutes (default 120) and rate_per_hour in dollars, and narrows by device, geofence or group. It separates what the data proves from what it can only bound:
- A recorded exit is fully evidenced. An open visit counts while the device keeps reporting.
- If the device re-entered the geofence without an exit event, the departure is inferred, so the time and money are a ceiling ("at most"). They are not added to the total.
- If the device went silent during the visit, the time is a floor ("at least") and the stop is unresolved. It is reported in
contact_lost_unresolved_cents, not in the total.
The report models only per-visit free time counted from geofence arrival, and an hourly rate prorated by the minute. Caps, billing increments, free time shared across stops and appointment-based clocks need a manual calculation. GPS timestamps support a claim; the rate confirmation and the signed bill of lading decide what is owed.
Questions to try
- "Which devices are inside a geofence right now?"
- "Show the trips for the last 7 days and the total distance in miles."
- "How long did each truck wait at our geofences last week, with 2 hours free and $75 an hour after that?"
- "Which workflows failed this week, and what did the failed runs have in common?"
Privacy
Whatever a tool returns goes to your AI provider as part of the conversation, including device names, driver names, GPS positions and addresses. Use a key for a workspace whose data you are allowed to share with that provider, and prefer narrow questions.
Troubleshooting
| Message | Fix |
|---|---|
SPATIALFLOW_API_KEY is not set. | The client didn't pass the key. Check the env block or the --env flag. |
The API key is invalid or expired (401). | Create a new key, or check that you copied the whole key. |
The API key lacks permission for this data, or the endpoint needs an owner or manager key (403). | Create a key with the permission from the table above. list_workflows also needs the key's owner to be a workspace owner or manager. |