@suverselabs/pingpoint-mcp
v0.4.2
Published
MCP server for freight tracking: your AI agent creates a load, the driver joins from an SMS link, then the agent reads live truck GPS, stop timeline, ETA and post-trip stats, or cancels it. Statuses come from GPS, never by hand.
Maintainers
Readme
@suverselabs/pingpoint-mcp
MCP server that gives an AI agent a live truck GPS position: create a freight load, PingPoint texts the driver an app link (onboarding takes about a minute — no ELD provider, no corporate account, no annual contract), then read live position, GPS track, stop timeline and ETA, and cancel a load you no longer need.
No account yet? A sandbox key is published at https://pingpoint.suverse.io/docs/#sandbox: same endpoints, no signup, and the load drives itself through the full cycle in about 20 minutes.
Install
Claude Code, one line:
claude mcp add pingpoint --env PINGPOINT_AGENT_KEY=sup_agent_… -- npx -y @suverselabs/pingpoint-mcpOr add to your MCP config (Claude Desktop: claude_desktop_config.json; Claude Code: .mcp.json; any MCP-capable agent works the same way):
{
"mcpServers": {
"pingpoint": {
"command": "npx",
"args": ["-y", "@suverselabs/pingpoint-mcp"],
"env": {
"PINGPOINT_AGENT_KEY": "sup_agent_…"
}
}
}
}Restart the agent and the tools appear.
Tools
| Tool | What it does | Returns | Price |
|---|---|---|---|
| create_load | Creates a freight load (multi-stop supported); PingPoint texts the driver app link to driverPhone | loadNumber, public trackingLink, driver web/app links, dedup flag | $0.65 |
| get_load_position | Live state of a load by load number | status, driver tracking state (driverTracking) with invite/open/decline timestamps, GPS track (last 500 points), stops with arrive/depart timestamps, distance covered, on-time flag, dwell times, ETA block | $0.02 |
| get_trip_stats | Post-trip summary over the whole GPS trip (best on a DELIVERED load) | stats with distance, duration, avg/max speed, hard accel/brake counts, city/highway/parked/night shares, GPS coverage, first/last ping | $0.02 |
| cancel_load | Cancels the load: status CANCELLED, tracking stops, nothing deleted, no refund | { ok, loadNumber, previousStatus, status, cancelledAt, trackingEndedAt } | free |
| update_load_status | Not part of the API — statuses are GPS-verified, see below | HTTP 501 OPERATION_NOT_AVAILABLE | — |
| get_pricing | Current USD price list for agent operations | { currency, prices } | free |
| get_balance | Prepaid balance that pays for creates and position reads | { currency, balanceUsd } | free |
Why update_load_status answers 501. PingPoint drives load statuses itself, from driver GPS and geofence events, so external status writes don't exist. Treat that as a data-integrity guarantee: a status you read was never hand-set by anyone; it is backed by actually recorded position. The tool is kept only so an agent that tries it gets a clear answer instead of a mystery. Delivery confirmation is likewise not a vendor operation — it belongs to the carrier flow, where the carrier files the BOL over Telegram.
Stops. A load carries 1–2 pickups and 1–3 deliveries; array order is the stop sequence. Each stop takes an optional window: date (start) and dateTo (end). onTime is measured against the dateTo of the last delivery, so without it that field stays null. Stops are fixed at creation — there is no add-stop tool.
Required to create a load: driverPhone (E.164 — the driver app link is sent to that number) plus pickups and deliveries arrays; every stop needs address, city, state, zip. Everything else is optional. customerRef doubles as a dedup key; pass the same idempotencyKey on retries so the balance is charged at most once.
Example — "where is my load?"
get_load_position with { "loadNumber": "LD-2026-042317" } returns:
{
"loadNumber": "LD-2026-042317",
"pingpointLoadId": "6f1c2d3e-8a45-4b9c-9d10-2e5f7a8b9c01",
"status": "IN_TRANSIT",
"createdAt": "2026-08-18T14:02:11.000Z",
"deliveredAt": null,
"driverTracking": "REPORTING",
"inviteSentAt": "2026-08-18T14:02:12.000Z",
"linkOpenedAt": null,
"declinedAt": null,
"distanceMiles": 412.7,
"onTime": null,
"delayMinutes": null,
"pickupDwellMinutes": 38,
"deliveryDwellMinutes": null,
"stops": [
{ "type": "PICKUP", "sequence": 1, "city": "Claremore", "state": "OK",
"windowFrom": "2026-08-18T15:00:00.000Z", "windowTo": "2026-08-18T19:00:00.000Z",
"arrivedAt": "2026-08-18T15:47:31.000Z", "departedAt": "2026-08-18T16:25:09.000Z" },
{ "type": "DELIVERY", "sequence": 2, "city": "Charlotte", "state": "NC",
"windowFrom": "2026-08-20T12:00:00.000Z", "windowTo": "2026-08-20T16:00:00.000Z",
"arrivedAt": null, "departedAt": null }
],
"gpsTrack": [
{ "lat": 36.3126, "lng": -95.6161, "speed": null, "heading": null, "ts": "2026-08-18T16:25:09.000Z" },
{ "lat": 35.4676, "lng": -94.3579, "speed": null, "heading": null, "ts": "2026-08-18T18:55:42.000Z" }
],
"pingCount": 214,
"eta": {
"nextStop": { "type": "DELIVERY", "sequence": 2, "city": "Charlotte", "state": "NC" },
"receivingWindow": { "from": "2026-08-20T12:00:00.000Z", "to": "2026-08-20T16:00:00.000Z" },
"distanceToNextStopMi": 611.4,
"driveTimeHours": 11.2,
"moving": true,
"stoppedForMinutes": null,
"etaWindow": { "from": "2026-08-20T13:05:00.000Z", "to": "2026-08-20T15:40:00.000Z" },
"tracking": { "state": "pinging", "noDataForMinutes": null },
"reason": null
}
}(gpsTrack shortened here; the API returns up to the last 500 points.)
Example — "how did the trip go?"
get_load_position answers "where is the truck now"; get_trip_stats answers "how did the finished trip go". On a DELIVERED load, get_trip_stats with { "loadNumber": "LD-2026-648319" } returns:
{
"loadNumber": "LD-2026-648319",
"loadId": "927741bc-dfd0-41ba-9e99-5c5031c756f9",
"stats": {
"dataPoints": 4785,
"durationSeconds": 69329,
"estimatedDistanceMiles": 486.591,
"avgSpeedMph": 25.27,
"maxSpeedMph": 88.22,
"hardAccelCount": 280,
"hardBrakeCount": 168,
"cityMilesPct": 9.96,
"highwayMilesPct": 88.65,
"parkedTimePct": 53.65,
"nightPct": 44.7,
"coveragePct": 100,
"firstAt": "2026-08-18T16:53:25.000Z",
"lastAt": "2026-08-19T12:08:54.000Z"
}
}Distances are miles, speeds are mph, percentages are 0–100, timestamps are UTC.
Is the driver actually sharing?
driverTracking in the get_load_position answer is the same word the PingPoint cabinet shows, so the agent can explain a silent load without guessing from an empty track:
| driverTracking | Meaning | Look at |
|---|---|---|
| NOT_BOUND | Driver link never opened in the app | inviteSentAt (SMS went out?), linkOpenedAt (opened in a browser but app not installed) |
| BOUND_SILENT | App bound to the load, no position yet | wait for the first ping |
| DECLINED | Driver tapped "Not now" on the location-consent screen | declinedAt; cleared once the driver agrees |
| REPORTING | Positions arriving | gpsTrack, eta |
| PAUSED_BY_DRIVER | Sharing paused from the app | eta.tracking.state === "driver_paused" |
null means the load has no driver yet.
Webhooks
Push notifications (pingpoint.load.created, pingpoint.load.updated, pingpoint.status.changed, pingpoint.load.completed, pingpoint.exception.raised, pingpoint.exception.resolved — the last two for LATE / NO_SIGNAL / LONG_DWELL) are configured in the cabinet, not through MCP tools: https://pingpoint.suverse.io/docs/webhooks
Getting a key
- Sign up at pingpoint.suverse.io (e-mail or Google/GitHub).
- In the cabinet open Integrations → Agent API and press Issue key.
- The
sup_agent_…key arrives by e-mail. PingPoint never stores the secret — if it's lost, re-issue from the same page.
Free operations work at zero balance. Paid ones debit your prepaid balance (top up in the cabinet, Billing); when it can't cover a call you get 402 INSUFFICIENT_FUNDS and nothing is charged.
Pricing
| Operation | Price | |---|---| | Create a load | $0.65 | | Read load position | $0.02 per request | | Trip summary stats | $0.02 per request | | Cancel a load | free | | Update load status | not available (501) | | Cancel a load | free | | Pricing / balance | free |
Environment
| Variable | Meaning |
|---|---|
| PINGPOINT_AGENT_KEY | Required. Your sup_agent_… key. |
| PINGPOINT_BASE_URL | Optional. Defaults to https://api.suverse.io. |
Built on @suverselabs/pingpoint-sdk — same contract, one implementation. Node ≥ 18.
Full API documentation: https://pingpoint.suverse.io/docs
