CargoMind MCP Server
Provides routing and geocoding capabilities using Google Maps Routes v2 and Geocoding APIs, used for shipment lane mapping, route planning, and disruption impact assessment.
Integrates with OpenAI GPT models (e.g., GPT-6.1 Sol, GPT-6 Luna, GPT-5 Mini) as a multi-model provider for conversation, planning, and fallback, enabling cross-vendor failover.
Provides an alternative mapping and routing fallback to Google Maps, used when Google Maps API is unavailable, ensuring continued geocoding and route calculations.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@CargoMind MCP Server Track shipment SHP-48291 and any active exceptions."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
CargoMind
A self-healing, multi-model, multi-agent logistics control tower.
Built on Google ADK, OpenAI GPT-6.1 Sol / GPT-6 Luna, Google Maps and MCP. Ask it about any shipment, lane, truck or SKU in an India-wide 3PL network. It plans, checks its own work and keeps answering when models, APIs or servers fail. The previous Gemini/Anthropic chain remains available with CARGOMIND_PROVIDER=multi.
▶ Open the live demo · Run it locally in 60 s · Criteria → proof · See it in action · Submission overview
Quickstart · Criteria map · Architecture · Demo script · Self-healing · Feedback loops · Deploy

23 | 3 vendors | 11 + 2 | 18 / 18 | 0 |
Google ADK agents using | Gemini → Claude / GPT → offline engine, failover per request | MCP tools + resources in our own server | eval scenarios pass, also under 30% injected chaos | API keys needed to run it |
Self-healing, seen live. One real request from our live runs, straight from the healing journal:
gemini-3.8-flash→ 429 RESOURCE_EXHAUSTED ·gemini-3.6-flash→ 429 ·anthropic/claude-sonnet-5-5→ error · served byopenai/gpt-5-mini— recovered. The operator just got their answer. Across those runs the journal recorded 19 automatic cross-vendor model recoveries.
Judge fast path: 90-second demo · criterion-by-criterion evidence · reproducible eval report. Verified: 106 tests pass, 18/18 offline scenarios succeed, routing F1 0.974. The timed demo uses the offline engine; live provider usage is visible in the trace.
Resilience evidence: 30% chaos eval also completed 18/18 scenarios, with 14 injected faults, 12 retries and 12 recorded recoveries. Both eval runs use the offline model and in-process MCP; CI separately exercises stdio MCP and Docker.
Simulation readiness
Open /simulation on the running server for a configurable logistics graph, explicit multi-agent handoffs, independently verified route decisions, and a forged-output rejection demo. The interface accepts operational IDs and numeric constraints; personal/contact fields are rejected. Proposals remain read-only.
Run uv run cargomind simulate --input scenario.json or POST a scenario to /api/simulation/run. See simulation schema and protocol, evaluation method, and raw-count benchmark report. The protocol is custom JSON handoff 1.0 over JSON-RPC 2.0; existing ADK agents invoke the same optimizer. Deterministic routing scores are distinct from LLM hallucination measurements.
Related MCP server: fleetsync-mcp
Contents
More depth: docs/ARCHITECTURE.md (sequence diagrams), docs/JUDGING.md (criteria checklist with file links), docs/DEMO_SCRIPT.md (3-minute live demo run-sheet).
See it in action
Disruption Autopilot: one sentence starts a multi-agent incident response. "Cyclone alert in Chennai, severity high: run disruption autopilot." The map draws the impact zone around Chennai and lights up every exposed lane. Then impact_assessor hands off to a ParallelAgent (reroute planner + notice drafter), and autopilot_commander writes the incident action plan for the operator to approve. In this capture the journal on the right shows Gemini hitting its quota and the run continuing on the next model.

Multimodal proof-of-delivery inspection that knows when not to guess. Attach a delivery photo and Gemini vision returns damage_detected, severity, findings and the next action. In this capture Gemini vision was over quota, so the local Pillow fallback answered instead: it marked the result degraded, explained why and asked for human review rather than inventing a verdict.
Watchtower acts before you ask. It scans SLAs, exceptions, stock, fleet and hub weather every 60 s. Each alert is a one-click question to the agent; weather alerts launch the autopilot.
The 30-second pitch
The problem. A logistics control tower runs on a dozen screens: a TMS for shipments, a WMS for stock, maps for routes, weather for risk, spreadsheets for dispatch, WhatsApp for customers. Most AI assistants for this job stop working the moment an API rate-limits, a model returns a 429 or a backend crashes. In operations that is the moment you need them.
CargoMind puts the whole control tower behind one conversation:
One concierge, many specialists. A conversational Gemini agent sends each request to 8 specialist agents: tracking, routes and risk, inventory, dispatch, customer comms, photo inspection, the ops briefing and the Disruption Autopilot. The graph has 23 ADK agents in total and uses every ADK workflow pattern:
LlmAgent+AgentTool,SequentialAgent,ParallelAgentandLoopAgent.Multi-model by design. Conversation, planning and vision tiers prefer Gemini models. The independent dispatch critic prefers Claude or GPT. The trace records which provider actually ran after any fallback. A deterministic offline rule-engine is the last link of every model chain.
It checks its own work. The dispatch planner and an independent critic run in a feedback loop. The critic checks truck capacity, driver hours, cold-chain and hazmat handling, SLA and weather. The planner revises until the plan is valid. Nothing is written to the database until you say "commit the plan".
It acts before you ask. The Watchtower scans the network every 60 s for SLA breach risk, exceptions, low stock, fleet problems and hub weather, and turns each alert into a one-click question. For a cyclone, flood, strike or closure, the Disruption Autopilot assesses the impact, plans reroutes and drafts customer notices in parallel, then hands the operator an incident action plan to approve.
It learns from the operator. Thumbs up or down, comments and "remember: always..." are turned into lessons. Those lessons are added to the agent's instructions on every turn.
It heals itself. The system has five layers of self-healing:
model failover across vendors
tool-argument repair, retries and circuit breakers
API fallbacks: Google Maps → OpenStreetMap → offline math
MCP-server failover
a Chaos Monkey slider so you can break things live and watch it recover
Every fault and recovery is written to a live healing journal.
Runs with zero keys.
git clone→uv sync→uv run cargomind webgives you a working system with no API keys at all. Add keys to switch on Gemini, Claude/OpenAI and Google Maps.
How CargoMind meets the judging criteria
Criterion | How CargoMind meets it | Where to look | Verify in under a minute |
Tool set: Agent SDK | Built on Google ADK 2.12. It uses |
| |
Tool set: Google products | Gemini in 4 roles (fast, pro, backup, multimodal vision). Google Maps Routes API v2 and Geocoding API. Cloud Run, Cloud Build and Secret Manager for deployment. The ADK Dev UI. Gemini CLI as an MCP client |
|
|
"No half-baked information: A–Z instructions" | This README covers a zero-key quickstart, setup for each OS, every API key step by step, every env var and command, the dashboard, ADK UI, MCP, Docker, Cloud Run and troubleshooting. | this file, | Follow Quickstart on a clean machine |
Multi-model agents | 4 model tiers across Gemini + Claude/OpenAI + an offline engine. When a Claude or OpenAI key is set, the critic deliberately runs on a different vendor from the planner. Images go to Gemini multimodal. Each answer is tagged with the model that served it ( |
| Dashboard trace and CLI show |
Conversational agents | The |
|
|
API calls | Google Routes v2 ( | Ask "Any weather risk on Mumbai → Pune today?" | |
MCP integration | CargoMind ships its own MCP server ( |
|
|
Feedback loop | (1) Planner and critic run in a | "Plan today's dispatch from Mumbai", then a thumbs-down with a comment | |
Self-healing agents | 5 layers: a resilient model chain with rollback, the | Set the dashboard Chaos slider to 30% and keep chatting | |
Submission: GitHub repo + README | MIT-licensed repo with CI (lint, tests, offline end-to-end demo under chaos, Docker build), a Dockerfile and a one-command Cloud Run deploy | CI badge at the top |
A per-criterion checklist with file and symbol pointers is in docs/JUDGING.md.
Architecture
System view
flowchart TB
subgraph IF["Interfaces"]
WEB["Mission-control dashboard<br/>FastAPI + SSE + Leaflet"]
CLI["CLI<br/>chat / demo / doctor<br/>autopilot / watchtower / eval"]
ADKUI["ADK Dev UI<br/>adk web src"]
EXT["External MCP clients<br/>Claude Desktop / Claude Code / Gemini CLI"]
end
subgraph RT["Google ADK runtime"]
RUN["Runner + session service<br/>stream_chat event stream"]
PLUG["SelfHealingPlugin<br/>arg repair / retries / breakers / reflect"]
CON["cargomind_concierge<br/>conversational orchestrator"]
SPEC["8 specialist agents<br/>exposed as AgentTools"]
WT["Watchtower<br/>background scan every 60 s"]
end
subgraph MODELS["ResilientLlm chain - one per agent"]
G["Gemini tier model"] --> GB["Gemini backup"] --> V2["Claude or GPT<br/>via LiteLLM"] --> OFF["Offline rule-engine"]
end
subgraph TOOLS["Tools"]
MCPT["ResilientMcpToolset<br/>MCP client with in-process failover"]
GEO["geo: routes, multi-stop, geocode"]
WX["weather: risk, route disruptions"]
PLAN["planning: quotes, ETA,<br/>propose / validate / commit plan"]
VIS["vision: proof-of-delivery photo"]
COMMS["comms: draft + simulated send"]
FB["feedback: remember_operator_feedback"]
end
MCPS["cargomind-logistics MCP server<br/>11 tools + 2 resources, stdio"]
DB[("SQLite<br/>shipments / fleet / stock / POs / outbox<br/>healing_events / feedback / preferences")]
WEB & CLI & ADKUI --> RUN --> CON --> SPEC
PLUG -.-|"wraps every tool and model call"| RUN
CON -.- MODELS
SPEC -.- MODELS
SPEC --> MCPT & GEO & WX & PLAN & VIS & COMMS
CON --> FB & PLAN
MCPT -- "stdio JSON-RPC" --> MCPS --> DB
EXT -- "stdio JSON-RPC" --> MCPS
PLAN & COMMS & FB --> DB
WEB --> WT --> DB
GEO --> GM["Google Routes v2 + Geocoding"] -.->|fallback| OSM["OSRM / Nominatim"] -.->|fallback| HAV["Haversine + gazetteer"]
WX --> OM["Open-Meteo"] -.->|fallback| SEAS["Seasonal heuristic"]
VIS --> GV["Gemini multimodal"] -.->|fallback| PIL["Pillow heuristic"]Agent graph
flowchart LR
U(["Operator"]) --> CON["cargomind_concierge<br/>LlmAgent - fast tier"]
CON -->|AgentTool| TRK["tracking_agent"]
CON -->|AgentTool| RRK["route_risk_agent"]
CON -->|AgentTool| INV["inventory_agent"]
CON -->|AgentTool| DP
CON -->|AgentTool| COM["comms_agent"]
CON -->|AgentTool| VI["vision_inspector<br/>vision tier"]
CON -->|AgentTool| OB
CON -->|AgentTool| AP
CON -->|tool| CMT["commit_dispatch_plan"]
CON -->|tool| REM["remember_operator_feedback"]
subgraph DP["dispatch_pipeline - SequentialAgent"]
direction TB
subgraph LOOP["plan_critique_loop - LoopAgent, max 4"]
PL["dispatch_planner<br/>pro tier"] --> CR["dispatch_critic<br/>critic tier = other vendor"]
CR -->|"issues -> revise"| PL
end
LOOP -->|"exit_loop when valid"| REP["dispatch_reporter"]
end
subgraph OB["ops_briefing - SequentialAgent"]
direction TB
subgraph FAN["signal_fanout - ParallelAgent"]
K["kpi_watch"]
R["risk_watch"]
S["stock_watch"]
end
FAN -->|"output_key state"| BW["briefing_writer"]
end
subgraph AP["disruption_autopilot - SequentialAgent"]
direction TB
IA["impact_assessor"] --> MF
subgraph MF["mitigation_fanout - ParallelAgent"]
RP["reroute_planner<br/>pro tier"]
ND["notice_drafter<br/>drafts only"]
end
MF -->|"output_key state"| AC["autopilot_commander<br/>incident action plan"]
endModel chain (one per agent, built by build_model(tier))
Tier | Used by | Chain, tried in order (links without a key are left out) |
| concierge, tracking, route/risk, inventory, comms, reporter, watchers, briefing writer, impact assessor, notice drafter, autopilot commander |
|
| dispatch planner, autopilot reroute planner |
|
| dispatch critic | Claude or GPT first (independent vendor) → |
| vision inspector |
|
The second vendor is Claude (anthropic/claude-sonnet-5-5) when ANTHROPIC_API_KEY is set. Otherwise it is GPT (openai/gpt-5-mini) when OPENAI_API_KEY is set. Both run through LiteLLM. Every model id can be overridden: see Configuration reference.
Sequence diagrams for a dispatch request and a self-healing fallback are in docs/ARCHITECTURE.md.
Feature tour
Agent | ADK pattern | Model tier | What it does | Tools |
|
| fast | Conversational front door. Understands the goal, calls one or more specialists in a single turn, asks clarifying questions and applies learned lessons | 8 specialist AgentTools, |
|
| fast | Status, location, history, ETA and SLA risk. Updates status only when asked | MCP: |
|
| fast | Road distance and time, multi-stop optimisation, weather and disruption risk, carrier quotes |
|
|
| fast | Stock levels, low-stock alerts, reorders (POs only when asked), warehouse info | MCP: |
|
| pro + critic + fast | Assigns pending shipments to own-fleet trucks. An independent critic checks capacity, driver hours, cold chain, hazmat, SLA, weather and duplicates. The planner revises (weather deferrals, driver swaps, team drivers, carrier hand-offs, corridor splits) until the plan is valid, then a report is written |
|
|
| fast | Empathetic, specific delay or delivery notices (email, SMS, WhatsApp). Sends only after approval, to a simulated outbox |
|
|
| vision | Proof-of-delivery photo inspection: damage, severity, findings, recommended action |
|
|
| fast | Morning briefing: KPIs, weather at 6 hubs and low stock are gathered in parallel, then written up as Headline, Risks and Actions | MCP |
|
| fast + pro | City-level disruption (cyclone, flood, strike, bandh, closure, landslide): finds exposed shipments, vehicles and warehouses, proposes reroutes/holds via an alternate hub, drafts customer notices (never sends) and writes an incident action plan. Nothing executes until the operator approves |
|
The seeded network. On first run CargoMind creates data/cargomind.db with a deterministic India-wide network. It contains 25 shipments (SHP-1001…SHP-1025, with real-world problems such as checkpost holds, monsoon delays, crushed cartons and hazmat), 5 warehouses (WH-BOM, WH-DEL, WH-BLR, WH-MAA, WH-HYD), 20 SKUs (some below their reorder point), 10 trucks (TRK-101…TRK-110, including a cold-chain reefer), 5 carriers (CR-01…CR-05) and a 20-city gazetteer. The gazetteer knows aliases such as Bangalore, Bombay, Madras and Gurgaon, and IATA-style codes such as BLR and BOM.
Quickstart
Works on Windows, macOS and Linux with zero API keys. You need Git and uv. uv installs Python 3.12 for you if you don't have it.
git clone https://github.com/Anandb71/cargomind
cd cargomind
uv sync
cp .env.example .env # Windows: copy .env.example .env
uv run cargomind web # open http://localhost:8080Then try uv run cargomind doctor (self-check), uv run cargomind demo (scripted 8-step scenario) or uv run cargomind chat (terminal chat).
With no keys, every answer comes from the offline rule-engine and the free or offline API fallbacks. The answers are structured and correct but templated. Add a free Gemini key to
.env(2 minutes) to get the full multi-model experience.
Full setup (Windows, macOS, Linux)
Prerequisites
Need | Why | Install |
Git | clone the repo | https://git-scm.com/downloads (or use GitHub's Code → Download ZIP) |
uv | Python + dependency manager (reads | see below |
Internet on first run | download dependencies; live APIs are optional | – |
(optional) Docker | container run | |
(optional) Google Cloud SDK | Cloud Run deploy | |
(optional) Node.js 18+ | MCP Inspector only |
Windows 10/11 (PowerShell)
# 1. Install uv, then CLOSE and REOPEN the terminal so `uv` is on PATH
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# 2. Get the code (two separate lines: Windows PowerShell 5.1 has no `&&`)
git clone https://github.com/Anandb71/cargomind
cd cargomind
# 3. Install Python 3.12 + all dependencies into .venv
uv sync
# 4. Create your settings file (all keys optional)
copy .env.example .env
notepad .env
# 5. Check, then run
uv run cargomind doctor
uv run cargomind webOpen http://localhost:8080. If you hit "path too long" errors or garbled characters, see Troubleshooting.
macOS
curl -LsSf https://astral.sh/uv/install.sh | sh # or: brew install uv
exec $SHELL -l # reload PATH
git clone https://github.com/Anandb71/cargomind && cd cargomind
uv sync
cp .env.example .env && open -e .env
uv run cargomind doctor
uv run cargomind web # http://localhost:8080Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
source "$HOME/.local/bin/env" 2>/dev/null || export PATH="$HOME/.local/bin:$PATH"
git clone https://github.com/Anandb71/cargomind && cd cargomind
uv sync
cp .env.example .env && ${EDITOR:-nano} .env
uv run cargomind doctor
uv run cargomind web # http://localhost:8080Verify the install
uv run cargomind doctor prints which providers are live, the configured model ids, live KPIs from the seeded database, and a smoke-test answer to "Where is SHP-1003?". The first line tells you the mode:
CargoMind | live: none | offline rule-engine fallback: on <- zero keys
CargoMind | live: gemini, claude, google_maps | offline rule-engine fallback: on <- keys picked upGetting the API keys
Every key is optional. Put keys in .env at the repo root. Empty values and placeholders that start with PASTE_, YOUR_ or < are ignored. Environment variables already set in your shell take precedence over .env. After changing .env, restart the command and re-run uv run cargomind doctor.
What each key unlocks
You set | Conversation and planning | Dispatch critic | Routes and geocoding | Weather | Photo inspection |
(nothing) | offline rule-engine | offline rule-engine | OSRM / Nominatim (free, no key) → haversine | Open-Meteo (free, no key) → seasonal heuristic | Pillow heuristic |
| Gemini fast / pro + backup | Gemini Pro | same as above | same | Gemini multimodal |
+ | + cross-vendor failover | Claude / GPT (independent vendor) | same | same | same |
+ | – | – | Google Routes API v2 + Geocoding | same | same |
| forces offline everywhere (no network at all) | offline | gazetteer + haversine | seasonal heuristic | Pillow heuristic |
1. Gemini API key (the brain)
Open https://aistudio.google.com/apikey and sign in with a Google account.
Click Create API key. Pick an existing Google Cloud project or let AI Studio create one.
Copy the key and paste it into
.env:GOOGLE_API_KEY=AIza...your-key...Run
uv run cargomind doctor. The first line should now includegemini.
The free tier has per-minute limits. When you hit one, Gemini returns HTTP 429. CargoMind retries, then fails over to the backup Gemini model, then to the second vendor, then to the offline engine, automatically (see Self-healing).
GOOGLE_GENAI_USE_VERTEXAI=true
GOOGLE_CLOUD_PROJECT=your-project-id
GOOGLE_CLOUD_LOCATION=us-central1Then authenticate once with gcloud auth application-default login. Enable the Vertex AI API on the project, and check that the model ids you configure are available in that location.
2. Google Maps API key (Routes API + Geocoding API)
Open https://console.cloud.google.com/ and select (or create) a project. Google Maps Platform requires a billing account on the project. It includes a monthly free usage allowance; check current pricing on the Maps Platform site.
Go to APIs & Services → Library. Search for Routes API and click Enable. Then search for Geocoding API and click Enable. CargoMind calls the Routes API v2 endpoint
routes.googleapis.com/directions/v2:computeRoutes, not the legacy Directions API.Open https://console.cloud.google.com/google/maps-apis/credentials and choose Create credentials → API key.
Recommended: click the key, open API restrictions, choose Restrict key and select Routes API and Geocoding API.
Paste it into
.env:GOOGLE_MAPS_API_KEY=AIza...your-maps-key...Run
uv run cargomind doctor. The first line should now includegoogle_maps. Route answers now showsource: google_routes. Before this they showedosrmorhaversinewithdegraded: true.
3. Second-vendor model: Claude or OpenAI (pick one)
Anthropic Claude (preferred when both are set):
Open https://console.anthropic.com/settings/keys. Add credits under Billing if the account is new.
Click Create Key, name it
cargomindand copy it.Add
ANTHROPIC_API_KEY=sk-ant-...to.env.
OpenAI:
Open https://platform.openai.com/api-keys. The account needs billing or credits.
Click Create new secret key and copy it.
Add
OPENAI_API_KEY=sk-...to.env.
The second vendor runs the dispatch critic first, so the plan is reviewed by a different model family from the one that wrote it. It is also the cross-vendor failover link for every other agent. If both keys are set, Claude is used.
Configuration reference
Every setting is an environment variable, read in src/cargomind/config.py. Put them in .env or export them in your shell. Shell values win.
Variable | Default | Purpose |
| (empty) | Gemini API key. Enables all Gemini tiers and Gemini vision |
|
|
|
| (empty) | Google Routes API v2 + Geocoding API |
| (empty) | Claude as the second vendor (critic + failover) |
| (empty) | GPT as the second vendor if no Anthropic key is set |
|
| Fast conversational / routing model |
|
| Deep-reasoning model for the planner (and critic fallback) |
|
| Same-vendor backup, tried before switching vendors |
| value of | Multimodal model for proof-of-delivery photos |
|
| LiteLLM model id for Claude |
|
| LiteLLM model id for OpenAI |
|
|
|
|
|
|
|
| Chaos Monkey fault-injection rate, |
|
| Retries per failed tool call (exponential backoff 0.3 s, 0.6 s, …) |
|
| Consecutive failures that open a circuit breaker |
|
| Seconds a breaker stays open before a half-open trial |
|
| Seconds per external HTTP call before falling back |
|
| Where the SQLite DB and uploaded photos live |
|
| SQLite database file |
|
|
|
|
| Dashboard port (Cloud Run sets it automatically) |
|
| Dashboard bind address |
|
| Uvicorn log level for the dashboard |
| set to | UTF-8 I/O for LiteLLM and child processes on Windows |
CLI reference
All commands run from the repo root with uv run …. They are installed as console scripts by uv sync.
Command | What it does |
| Shows live providers and model ids, prints KPIs from the DB and runs a one-question smoke test |
| Starts the mission-control dashboard and API at http://localhost:8080 (API docs at |
| Interactive multi-turn chat in the terminal. Shows tool calls ( |
| Runs the scripted 8-step scenario from Demo script in one session, then prints self-healing stats |
| Same, with 30% of tool and model calls failing on the first try, to show self-healing |
| Runs the |
| Re-seeds the demo database (shipments, fleet, stock, POs, outbox) |
| Runs the Disruption Autopilot steps directly (impact → reroutes → notice drafts) and prints the actions. |
| Same, but through the full multi-agent concierge ( |
| One Watchtower scan: prints every active alert with severity, detail and the suggested question |
| Runs the 18-scenario eval harness and writes the report. All flags pass through to |
| Google ADK Dev UI at http://localhost:8000. Pick cargomind |
| ADK's own terminal runner for the same agent |
| Aliases for |
| Test suite |
Mission-control dashboard
uv run cargomind web # http://localhost:8080 (other port: --port 8090)Area | What you see and do |
Top bar | Status pills showing which models and APIs are live, the network clock (IST), and the Chaos Monkey slider (0–60%), which injects transient faults into tool and model calls live |
Watchtower | Proactive alerts (critical first) from the background scan. Click an alert to send its suggested question to the agent, or scan on demand |
Network pulse | KPI tiles: on-time rate, delayed and critical shipments, fleet utilisation, open POs and more. Refreshes every 10 s |
Shipments | Filterable table (ID, customer, city) of the seeded network |
Network map | Leaflet + OpenStreetMap map of hubs, cities and shipment lanes, coloured by status |
Ops agent chat | Streaming conversation with suggested questions, a new session button and photo attach (button, paste or drag-and-drop). The trace shows agent hand-offs, every tool call with its arguments and results, and the model that served each answer. Thumbs up/down + comment on answers feed the learning loop |
Self-healing journal | Live SSE feed of |
Method | Path | Purpose |
|
|
|
|
| Upload a delivery photo (multipart |
|
| Serve an uploaded photo |
|
|
|
|
| Distilled lessons + satisfaction stats |
|
| Network data (filters: |
|
| Recent journal events, stats, circuit-breaker states, chaos rate |
|
| SSE live healing journal |
|
| Read or set the chaos rate ( |
|
| Active Watchtower alerts ( |
|
| Run a Watchtower scan now; returns new and active alerts |
|
| Mode, live providers, component presence, library versions |
Example:
curl -N -X POST http://localhost:8080/api/chat -H "Content-Type: application/json" \
-d '{"session_id":"curl-1","message":"Where is SHP-1003?"}'ADK Dev UI
Google ADK ships a developer UI. CargoMind's package exposes its ADK App (agent graph + SelfHealingPlugin) in src/cargomind/__init__.py, so the dev UI runs exactly the same system.
uv run adk web src # http://localhost:8000
uv run adk web --port 8001 src # if 8000 is busyOpen http://localhost:8000. In the agent dropdown (top left), select
cargomind.Chat as usual, for example "Plan today's dispatch from Mumbai".
Use the Events list to inspect every model request and response, function call and function response, including the planner ⇄ critic iterations.
Use State to see the session state the agents pass to each other, such as
current_plan,plan_issues,dispatch_plan_summary,kpi_snapshot,risk_snapshotandstock_snapshot.
Notes: adk web also reads the repo-root .env through config.py. On Windows, ADK turns off auto-reload by itself, because reload is incompatible with the MCP stdio subprocess. For a terminal-only ADK session use uv run adk run src/cargomind.
MCP server
cargomind-logistics is a real Model Context Protocol server built with the Python MCP SDK. It exposes the operational database over stdio.
Tool | Arguments | Purpose |
|
| Status, location, carrier/vehicle, ETA, promised date |
|
| Filtered list, critical first |
|
| Event timeline |
|
| Write a status change + event |
|
| Stock vs reorder points |
|
| Raise a purchase order |
|
| Fleet, capacity, driver hours, refrigeration |
|
| Assign a truck to a shipment |
| – | Carriers, modes, rates, reliability |
| – | Warehouse directory |
| – | Network KPIs |
Resources: logistics://kpis and logistics://warehouses (JSON). A look-up that misses never throws. It returns {"status": "error", "error": ..., "suggestions": [closest valid IDs]} so the calling LLM can correct itself.
How CargoMind's own agents use it
The specialists get their MCP tools from mcp("track_shipment", ...) in mcp_tools.py. That creates a ResilientMcpToolset wrapping ADK's McpToolset, which spawns python -m cargomind.mcp_server.server over stdio. If the server can't start or stops answering, the toolset journals the fault, opens a breaker and serves the same tool names in-process, so the conversation never breaks. After the cooldown it reconnects and journals recovered.
Use it from Claude Desktop
Find the absolute path to your clone and to
uv(where uvon Windows,which uvon macOS/Linux).Open Claude Desktop → Settings → Developer → Edit Config. That opens
claude_desktop_config.json:Windows:
%APPDATA%\Claude\claude_desktop_config.jsonmacOS:
~/Library/Application Support/Claude/claude_desktop_config.json
Paste the contents of
deploy/claude_desktop_config.example.jsonand replace the path:{ "mcpServers": { "cargomind-logistics": { "command": "uv", "args": ["--directory", "/ABSOLUTE/PATH/TO/cargomind", "run", "cargomind", "mcp"], "env": { "PYTHONUTF8": "1" } } } }On Windows, escape backslashes (
"C:\\Users\\you\\cargomind"). If Claude Desktop can't finduv, put the full path touvin"command".Fully quit Claude Desktop (including the tray icon) and reopen it. Then ask: "Using cargomind-logistics, which critical shipments are delayed?"
The MCP server and the dashboard share data/cargomind.db. A status change made from Claude Desktop appears on the dashboard's next refresh.
Use it from Claude Code, Gemini CLI or the MCP Inspector
# Claude Code
claude mcp add cargomind-logistics -- uv --directory /ABSOLUTE/PATH/TO/cargomind run cargomind mcp
# MCP Inspector (needs Node.js 18+): browse tools, call them by hand
npx @modelcontextprotocol/inspector uv --directory /ABSOLUTE/PATH/TO/cargomind run cargomind mcpGemini CLI: add this to ~/.gemini/settings.json, then run /mcp inside Gemini CLI to see the tools.
{
"mcpServers": {
"cargomind-logistics": {
"command": "uv",
"args": ["--directory", "/ABSOLUTE/PATH/TO/cargomind", "run", "cargomind", "mcp"]
}
}
}Demo script
These are the same 8 prompts uv run cargomind demo runs, in one session. Type them into the dashboard or cargomind chat to drive them yourself. Wording varies by model. In zero-key mode the rule-engine answers with structured markdown tables.
# | Prompt | Routed to | What happens / what to look for |
1 |
|
| A |
2 |
|
| MCP |
3 |
|
|
|
4 |
|
|
|
5 |
|
| The feedback loop: the planner (pro tier) calls |
6 |
|
|
|
7 |
|
|
|
8 |
| concierge → | Stored as a lasting PREFERENCE. It appears under Lessons learned and is added to the concierge's instruction from the next turn on |
Bonus prompts that show off specific features:
Prompt | Shows |
| Human-in-the-loop: |
Attach a photo + | Gemini multimodal inspection: |
| Argument repair: watch for |
| Google Routes waypoint optimisation (or the OSRM / haversine fallback) |
| A multi-domain turn: the concierge calls several specialists in one go |
| Write action through MCP |
| The Disruption Autopilot: impact → reroutes + notice drafts in parallel → incident action plan awaiting approval |
The timed, click-by-click version for presenting is in docs/DEMO_SCRIPT.md.
Self-healing deep dive
CargoMind assumes things will break: free-tier quotas, flaky public APIs, hallucinated arguments, crashed subprocesses. It has five layers of defence, and every action is written to a journal you can watch live.
# | Layer | Where | What it heals |
1 | ResilientLlm model chain | Each agent's model is a chain: Gemini tier → Gemini backup → Claude/GPT → offline rule-engine. Transient errors (408/429/5xx, timeouts) are retried in place (0.4 s, 1.0 s). Other errors, such as a bad key or an unknown model, fall straight through. The request is rolled back to a pristine snapshot before every attempt. Each model has a circuit breaker (3 failures → skipped for 60 s). Every response is stamped | |
2 | SelfHealingPlugin (runner-wide ADK plugin) | before_tool: argument repair ( | |
3 | API provider fallback chains | Routes: Google Routes v2 → OSRM → haversine × road factor. Geocoding: Google → Nominatim → gazetteer. Weather: Open-Meteo → seasonal heuristic. Vision: Gemini → Pillow heuristic. Every result carries | |
4 | ResilientMcpToolset | If the MCP server can't be spawned or crashes, it serves identical tools in-process, opens a breaker and reconnects after the cooldown | |
5 | Chaos Monkey + healing journal |
|
Journal event kinds: fault (injected or real failure) · retry · fallback (next model or provider) · breaker_open / breaker_close · arg_repair · reflect (hint handed to the LLM) · recovered.
How to demo it
Recipe | Steps | What you'll see |
Chaos slider (best on stage) | Dashboard → drag Chaos Monkey to 30% → ask "Morning ops briefing" | The journal fills with |
Scripted chaos run |
|
|
Chaos for a whole session | Add | Every interface runs under chaos |
Kill Gemini, deterministically |
| Every Gemini call fails. Watch |
Bad API key | Set | Non-transient error → immediate fallback down the chain. The breaker then skips Gemini for 60 s |
Broken arguments | Ask "where is shp 1003" or "route bangalore to madras" |
|
No internet |
| All tools serve offline estimates flagged |
Feedback loops deep dive
CargoMind runs four feedback loops, two driven by agents and two by humans.
1. Agent ⇄ agent: plan → critique → revise (LoopAgent).
dispatch_planner (pro tier) calls propose_dispatch_plan. That builds a quick greedy plan assigning pending shipments to available own-fleet trucks, and writes state["current_plan"].
dispatch_critic runs on the critic tier: a different vendor when a Claude or OpenAI key is set. It calls validate_dispatch_plan, which checks every assignment for:
vehicle capacity
driver duty hours
cold-chain and dangerous-goods handling
weather risk
SLA for critical and express loads
diverging multi-drop routes, duplicate assignments, and critical shipments left without transport
Each issue has a severity (blocker / warning) and a suggested fix. The critic writes them to state["plan_issues"] and returns {valid, issues, score}.
If there are blockers, the next loop iteration runs the planner again. propose_dispatch_plan then revises the plan to fix them, using weather deferrals, driver-hour swaps, team drivers, carrier hand-offs for priority loads or corridor splits. When the plan is valid, the critic calls exit_loop. The loop is capped at 4 iterations. dispatch_reporter then summarises the revisions, fixed issues, assignments and deferred shipments. commit_dispatch_plan refuses an unvalidated revision unless the operator insists. Carrier hand-offs come back as booking actions; they are never auto-booked.
2. Human → agent: ratings, corrections and preferences that persist.
In the dashboard, the thumbs up/down + comment on each answer goes to
POST /api/feedback, which writes the SQLitefeedbacktable.In conversation, when the operator corrects the agent or says "remember / always / never / prefer…", the concierge calls
remember_operator_feedback. Text with always / never / prefer / avoid is also saved as a lasting preference.lessons()distils all of this into at most 8 deduplicated lines:PREFERENCE: …, thenAVOID: …(from negative comments), thenKEEP: …(from positive ones).render_lessons_block()appends those lines to the concierge's instruction. The instruction is a function (concierge_instruction), so ADK re-evaluates it on every turn. Feedback changes behaviour on the very next message, with no restart.The dashboard's Lessons learned panel shows what is currently being applied.
Check it from the terminal:
uv run python -c "from cargomind.feedback.store import render_lessons_block, stats; print(render_lessons_block()); print(stats())"3. Human-in-the-loop gates. Plans are only applied after "commit the plan". Notifications are only sent after approval. POs are raised and statuses changed only when explicitly asked. The agent proposes and the operator decides.
4. Tool → LLM: reflect and retry. Failed or not-found tool calls come back as structured errors with suggestions (closest valid IDs) and a healing_hint. Agents are instructed to correct their arguments and retry once before asking the user.
Disruption Autopilot and Watchtower
Disruption Autopilot (autopilot.py) handles a city-level event (cyclone, flood, strike, bandh, road closure, landslide) as one workflow. The concierge calls it as AgentTool(disruption_autopilot) when a message mentions autopilot, cyclone, flood, strike, bandh, closure, disruption, landslide or "alert in".
Step | Agent | Tool | Output ( |
1 |
|
| Exposed shipments, vehicles and warehouses, plus hub weather → |
2a (parallel) |
|
| Reroute / hold actions via an alternate hub, critical first, and vehicle moves out of the zone → |
2b (parallel) |
|
| Customer notice drafts for urgent shipments ( |
3 |
| – | Incident action plan: Situation, Exposure, Actions (owner + deadline), Customer comms, Approval needed |
The workflow produces proposals and drafts for operator review. Reroutes and vehicle moves must be applied manually in the transport system. To queue an approved notice in the simulated outbox, name its shipment, channel and message when asking the comms agent; there is no batch approval command. run_autopilot(city, event, severity) runs the three tools directly without an LLM; the CLI and tests use it.
uv run cargomind autopilot Chennai --event cyclone --severity high # direct tools, instant
uv run cargomind autopilot Chennai --event cyclone --severity high --agent # full multi-agent workflowWatchtower (watchtower.py) raises alerts before the operator asks. uv run cargomind web starts run_watchtower(60) as a background task in the server lifespan (set CARGOMIND_WATCHTOWER=0 to disable it). Each scan (scan_once() → {"new": [...], "active": [...]}) checks:
Check | Alert kind | Raised when |
SLA breach risk |
| ETA is later than |
Exceptions |
| Shipment status is |
Low stock |
| SKU below its reorder point with no open PO |
Fleet |
| Fuel below 20% or driver hours below 1 h |
Hub weather |
| Medium or high 24 h weather risk at one of 6 hubs. The suggested prompt runs the Disruption Autopilot |
Every alert has id, kind, severity, title, detail and a suggested_prompt. Existing alerts from a failing source are retained with stale: true until a healthy scan updates or resolves them. Other checks continue. See the alerts in the dashboard's Watchtower panel, at GET /api/alerts / POST /api/alerts/scan, or with uv run cargomind watchtower.
Evaluation
uv run cargomind eval --mode offline --out docs/EVAL_REPORT.md runs 18 scenarios (one fresh session each) through the real agent graph and scores routing, answer content, latency and healing events. Latest run, in offline rule-engine mode (no API keys, chaos 0%, in-process MCP). Full report: docs/EVAL_REPORT.md.
Metric | Value |
Task success | 18/18 (100%) |
Answer pass rate | 100% |
Routing precision / recall / F1 (micro) | 0.950 / 1.000 / 0.974 |
Routing exact-set match | 94.4% |
Latency p50 / p95 | 0.47 s / 2.85 s |
Runtime errors | 0 |
Every scenario reached the right specialist (recall 1.0). Precision is below 1.0 because one prompt is routed to an extra agent: the feedback prompt also calls tracking_agent. The harness caught two real rule-engine bugs, and both are fixed with regression tests: "Which" was parsed as warehouse WH-ICH, and "SKUs" was parsed as SKU-S. These numbers are for the offline rule-engine; live-model results will differ, so rerun with your keys (--mode online) to measure them.
Project structure
cargomind/
├── src/cargomind/
│ ├── __init__.py # exposes `app` / `root_agent` lazily, so `adk web src` finds the agent
│ ├── agent.py # the agent graph: concierge + 8 specialists (23 ADK agents), App + plugin
│ ├── autopilot.py # Disruption Autopilot: impact -> parallel reroutes + notice drafts -> action plan
│ ├── watchtower.py # proactive monitor: SLA, exception, stock, fleet and weather alerts
│ ├── runtime.py # ADK Runner, sessions, stream_chat() merging agent + healing events
│ ├── cli.py # `cargomind` command: chat / demo / web / mcp / doctor / reset-db / autopilot / watchtower / eval
│ ├── config.py # every env var, model ids, key detection, mode summary
│ ├── mcp_tools.py # ResilientMcpToolset: MCP client with in-process failover
│ ├── data/
│ │ ├── gazetteer.py # 20 Indian cities, aliases, IATA codes, haversine
│ │ └── db.py # SQLite schema, deterministic seed, queries, KPIs
│ ├── mcp_server/
│ │ └── server.py # cargomind-logistics MCP server: 11 tools + 2 resources (stdio)
│ ├── tools/
│ │ ├── geo.py # Google Routes v2 / Geocoding -> OSRM / Nominatim -> haversine
│ │ ├── weather.py # Open-Meteo -> seasonal heuristic
│ │ ├── planning.py # carrier quotes, ETA, dispatch propose / validate / commit
│ │ ├── vision.py # Gemini multimodal proof-of-delivery inspection -> Pillow heuristic
│ │ └── comms.py # customer notification drafts + simulated outbox
│ ├── healing/
│ │ ├── resilient_llm.py # cross-vendor model chain with retries, breakers, request rollback
│ │ ├── offline_llm.py # deterministic rule-engine that speaks the ADK model protocol
│ │ ├── plugin.py # SelfHealingPlugin (ADK BasePlugin)
│ │ ├── breaker.py # circuit breakers
│ │ ├── chaos.py # Chaos Monkey fault injection
│ │ └── journal.py # healing journal: ring buffer + SQLite + pub/sub
│ ├── evals/
│ │ ├── scenarios.py # 18 eval scenarios with expected routing and answer checks
│ │ └── runner.py # eval harness -> docs/EVAL_REPORT.md
│ ├── feedback/
│ │ └── store.py # ratings, preferences, lessons learned, remember_operator_feedback
│ └── web/
│ ├── server.py # FastAPI: REST + SSE chat / healing stream / alerts; starts the Watchtower
│ └── static/ # no-build dashboard (HTML/CSS/JS, Leaflet)
├── tests/ # pytest suite (data, MCP server, healing, feedback, offline LLM, autopilot, ...)
├── docs/ # ARCHITECTURE.md, JUDGING.md, DEMO_SCRIPT.md, CONTRACTS.md, EVAL_REPORT.md
├── deploy/
│ ├── cloudrun.sh # one-command Cloud Run deploy (Secret Manager aware)
│ └── claude_desktop_config.example.json
├── .github/workflows/ci.yml # lint + tests + offline e2e demo under chaos + Docker smoke test
├── Dockerfile / .dockerignore
├── pyproject.toml / uv.lock / .python-version
├── .env.example # copy to .env; every key optional
└── LICENSE # MITTesting and CI
uv run pytest # full suite
uv run pytest -q tests/test_healing.py
uv run ruff check src # lintThe tests are deterministic and need no keys. To match CI exactly (no network, real MCP stdio server):
CARGOMIND_OFFLINE=1 CARGOMIND_MCP_LOCAL=0 uv run pytest -q # macOS / Linux
$env:CARGOMIND_OFFLINE="1"; $env:CARGOMIND_MCP_LOCAL="0"; uv run pytest -q # PowerShellGitHub Actions runs on every push and PR, with zero keys:
uv syncruff check(advisory)pytest -qcargomind doctorthe full 8-step demo under 30% chaos, end to end through the real MCP stdio server
a separate job that builds the Docker image, runs it and waits for
/api/health
Docker
docker build -t cargomind .
docker run -p 8080:8080 --env-file .env cargomind # with your keys
docker run -p 8080:8080 cargomind # zero keysOpen http://localhost:8080. Useful variations:
docker run -p 8080:8080 --env-file .env -v cargomind-data:/app/data cargomind # keep DB + feedback across restarts
docker run -p 9000:9000 -e PORT=9000 cargomind # different port
docker run -p 8080:8080 -e CARGOMIND_CHAOS=0.3 cargomind # start with chaos onThe image is python:3.12-slim + uv. It installs exactly what uv.lock pins (uv sync --frozen --no-dev), runs as a non-root user, respects $PORT, and has a health check on /api/health. .env is never copied into the image.
Deploy to Google Cloud Run
Hosted Vercel demo
The public demo runs at https://cargomind-lilac.vercel.app with live provider keys configured through the Vercel CLI. Anonymous dashboard, health, KPI and static-asset requests returned HTTP 200. A live SSE tracking request completed with tool results and a final answer; its trace recorded Gemini backup and OpenAI providers.
Vercel uses temporary per-instance SQLite storage, uploads and session memory. Data can reset on a cold start. Click Scan now for Watchtower alerts; the continuous background scanner is disabled on serverless hosting. Local and Cloud Run operation retain the background scanner.
The deployment entrypoint is app.py; vercel.json selects FastAPI and a 300-second function limit. From a linked project, deploy with vercel --prod. Set provider keys through vercel env add NAME production and redeploy; keep secrets out of source control.
Google Cloud Run
Prerequisites: a Google Cloud project with billing enabled, and the gcloud CLI. Or use Cloud Shell, which already has everything.
gcloud auth login
gcloud config set project YOUR_PROJECT_ID
./deploy/cloudrun.sh # Windows: run from Git Bash, WSL or Cloud Shelldeploy/cloudrun.sh does the following:
Enables Cloud Run, Cloud Build and Artifact Registry.
Reads your keys from
.envwithout executing it.Stores each key in Secret Manager (
cargomind-google-api-key, …) and grants the runtime service accountsecretAccessor.Runs
gcloud run deploy --source .inasia-south1(Mumbai).Prints the URL.
Options:
--plain-envpasses the keys as plain env vars instead of secrets.--no-keysdoes a zero-key deploy.REGION=,SERVICE=,PROJECT_ID=,ENV_FILE=andSERVICE_ACCOUNT=override the defaults.
Manual equivalent (plain env vars, quickest):
gcloud run deploy cargomind --source . --region asia-south1 --allow-unauthenticated \
--memory 1Gi --timeout 3600 --max-instances 1 --session-affinity \
--set-env-vars GOOGLE_API_KEY=your-gemini-key,GOOGLE_MAPS_API_KEY=your-maps-key,ANTHROPIC_API_KEY=your-claude-keyManual equivalent with Secret Manager (recommended for anything public):
printf '%s' "your-gemini-key" | gcloud secrets create cargomind-google-api-key --data-file=-
PROJECT_NUMBER=$(gcloud projects describe $(gcloud config get-value project) --format='value(projectNumber)')
gcloud secrets add-iam-policy-binding cargomind-google-api-key \
--member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
gcloud run deploy cargomind --source . --region asia-south1 --allow-unauthenticated \
--memory 1Gi --timeout 3600 --max-instances 1 --session-affinity \
--set-secrets GOOGLE_API_KEY=cargomind-google-api-key:latestWhy these flags:
--max-instances 1+--session-affinitykeep chat sessions, the journal and the demo SQLite DB on one instance.--timeout 3600keeps dashboard SSE streams open.Cloud Run's filesystem is in-memory, so the demo DB re-seeds on each cold start. That is by design for a demo. See the Roadmap for managed persistence.
Troubleshooting and FAQ
Close and reopen the terminal after installing uv. If it still fails, add uv's directory to PATH: %USERPROFILE%\.local\bin on Windows, ~/.local/bin on macOS and Linux. On Windows, if the installer is blocked, run exactly powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex".
Run git config --global core.longpaths true. Enable Win32 long paths once, from an Administrator PowerShell:
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force
Then restart. Or simply clone to a short path such as C:\src\cargomind.
CargoMind already sets PYTHONUTF8=1 for child processes and switches the CLI to UTF-8 output. If your console still complains, set it for the shell before running: $env:PYTHONUTF8="1" (PowerShell) or set PYTHONUTF8=1 (cmd). Windows Terminal renders the output best. Python 3.12+ is required, and uv sync installs it.
Windows PowerShell 5.1 doesn't support &&. Run the commands on separate lines (as in the Windows setup above), or use PowerShell 7+.
Use uv run cargomind web --port 8090, or set PORT=8090. For the ADK UI use uv run adk web --port 8001 src. To find the process holding the port, run netstat -ano | findstr :8080 (Windows) or lsof -i :8080 (macOS/Linux).
Nothing to do: this is exactly what the self-healing chain is for. CargoMind retries twice, fails over to CARGOMIND_GEMINI_BACKUP, then to Claude/GPT, then to the offline engine. The model's breaker skips it for 60 s, and the journal shows each step. For sustained heavy use, enable billing on the AI Studio project or point CARGOMIND_GEMINI_FAST at a model with more quota.
Your key may not have access to a default model id. The chain falls back automatically. To fix it permanently, set CARGOMIND_GEMINI_FAST, CARGOMIND_GEMINI_PRO or CARGOMIND_GEMINI_BACKUP (or the Claude / OpenAI ids) in .env to models your account lists. uv run cargomind doctor prints the ids in use.
No usable model key was found, or every online model failed. Run uv run cargomind doctor. If live: is none, your .env is missing, empty or still has placeholders. It must be at the repo root and named exactly .env. Otherwise, check the healing journal for the fallback reason, for example an invalid key.
Google Maps isn't configured or rejected the call. Check that Routes API and Geocoding API are both enabled on the key's project, that billing is on, and that the key restrictions allow those APIs. Until then, the free OSRM or offline estimates are used and clearly flagged.
Use absolute paths: the repo path in --directory and, if needed, the full path to uv in "command". Fully quit Claude Desktop, including the tray icon, before reopening. Logs are in %APPDATA%\Claude\logs\mcp*.log (Windows) or ~/Library/Logs/Claude/mcp*.log (macOS). Run uv sync once in the repo first.
That's correct. It is a stdio server waiting for an MCP client. Press Ctrl+C, then connect it from Claude Desktop, Claude Code, Gemini CLI or the MCP Inspector.
uv run cargomind reset-db re-seeds the operational data. For a completely clean slate, including feedback, lessons and the journal history, stop all CargoMind processes and delete data/cargomind.db*. It is recreated on the next start.
Set CARGOMIND_OFFLINE=1. No network calls are made, and the whole demo, including dispatch planning, briefings and self-healing, still works on seeded data.
No. send_notification writes to a simulated outbox table (GET /api/outbox). Nothing leaves the machine.
On newer projects, source deploys build with the Compute Engine default service account. Grant it the Cloud Run Builder role:
gcloud projects add-iam-policy-binding YOUR_PROJECT_ID --member="serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com" --role="roles/run.builder"
If you switch between --plain-env and Secret Manager on an existing service and see "already set with a different type", remove the old variables first, for example gcloud run services update cargomind --region asia-south1 --remove-env-vars GOOGLE_API_KEY.
Roadmap
Real integrations: carrier and TMS APIs, India's e-way bill and ULIP data, live GPS telematics in place of the seeded fleet.
Managed persistence: Firestore or Cloud SQL for operations data, sessions and the healing journal, so the system can scale beyond one instance.
Vertex AI Agent Engine deployment, and live-model runs of the eval harness in CI.
Optimisation: an OR-Tools VRP solver behind
propose_dispatch_plan, with time windows and cold-chain constraints.Learning: embedding-based retrieval of past feedback and incidents, plus per-operator preference profiles.
A2A protocol so carrier and warehouse partners' agents can negotiate directly with CargoMind.
Voice control-tower mode with the Gemini Live API. Auth / RBAC on the dashboard. OpenTelemetry → Cloud Trace.
Team
Name | Role | GitHub |
Anand B | Core platform, agents, self-healing and dashboard | |
Junaid Ahamed | Disruption Autopilot, Watchtower, CLI and evaluations |
License
MIT © 2026 CargoMind contributors.
Built with Google ADK, Gemini, Google Maps Platform, the Model Context Protocol, LiteLLM, FastAPI, Leaflet, OpenStreetMap / OSRM and Open-Meteo. Map data © OpenStreetMap contributors.
Available Tools
11 toolsassign_vehicleA
Assign an own-fleet vehicle to a shipment. Checks capacity and maintenance status; idempotent.
Args:
shipment_id: Shipment ID such as "SHP-1007".
vehicle_id: Vehicle ID such as "TRK-105".
Returns:
{"status": "ok", "warnings": [...], "vehicle": {...}} - warnings flag soft issues (vehicle in another
city, driver near the 10h limit, low fuel, cold-chain mismatch). Errors suggest alternative vehicles.
Inputs: vehicle_id (required), shipment_id (required). Returns: object
check_inventoryA
Check stock levels per SKU and warehouse, including low-stock flags and any open purchase order.
Args:
sku: SKU ID ("SKU-107") or product name fragment ("insulin", "gloves"). Empty = all SKUs.
warehouse_id: Warehouse ID ("WH-BLR"), code ("BLR") or city ("Bangalore"). Empty = all warehouses.
low_stock_only: If true, only lines at or below their reorder point.
Returns:
{"status": "ok", "count", "low_stock_count", "items": [{sku, name, warehouse_id, qty_on_hand,
reorder_point, shortfall, low_stock, open_po, ...}]}.
Inputs: sku, warehouse_id, low_stock_only. Returns: object
create_reorderA
Raise a purchase order to replenish a SKU at a warehouse. Safe to retry: if an open PO already exists for the line it is returned with duplicate=true instead of creating another.
Args:
sku: SKU ID such as "SKU-107".
warehouse_id: Warehouse ID ("WH-BLR"), code or city.
qty: Units to order; 0 = automatic (tops stock up to 2x reorder point, min standard reorder qty).
Returns:
{"status": "ok", "duplicate": bool, "purchase_order": {id, qty, supplier, expected_by, ...}, "message"}.
Inputs: sku (required), warehouse_id (required), qty. Returns: object
get_kpisB
Network health snapshot: on_time_rate (%), in_transit, delayed, exceptions, delivered_today, low_stock_skus, fleet_utilization (%), open_pos, critical_active and counts by status.
Returns:
KPI dict with status="ok".
Inputs: no named parameters. Returns: object
list_carriersA
List carrier partners with modes, INR rate card (base_rate_per_km, per_kg_rate), reliability (0-1) and average speed - use for quoting and choosing a carrier.
Returns:
{"status": "ok", "count", "carriers": [...]}.
Inputs: no named parameters. Returns: object
list_shipmentsA
List shipments, filtered and sorted (active first, critical first, then earliest promised delivery).
Args:
status: One of created, picked_up, in_transit, delayed, out_for_delivery, delivered, exception,
or "active" (anything not yet delivered/exception). Empty = all.
city: City name or alias (e.g. "Bangalore", "Bombay"); matches origin, destination or current city.
priority: standard, express or critical. Empty = all.
limit: Maximum rows to return (default 25).
Returns:
{"status": "ok", "count": n, "shipments": [...]} each with is_late / delay_hours.
Inputs: city, limit, status, priority. Returns: object
list_vehiclesA
List own-fleet vehicles with capacity, current load, driver hours remaining and fuel.
Args:
status: available, on_route or maintenance. Empty = all.
city: Current city of the vehicle (name or alias). Empty = all.
Returns:
{"status": "ok", "count", "vehicles": [{id, type, capacity_kg, remaining_capacity_kg, status,
current_city, driver_name, driver_hours_today, driver_hours_remaining, fuel_pct, refrigerated}]}.
Inputs: city, status. Returns: object
list_warehousesA
List warehouses with city, coordinates, utilisation %, cold-chain capability and low-stock line count.
Returns:
{"status": "ok", "count", "warehouses": [...]}.
Inputs: no named parameters. Returns: object
shipment_historyA
Full chronological event trail (scans, checkpoints, delays, assignments) for one shipment.
Args:
shipment_id: Shipment ID such as "SHP-1003".
Returns:
{"status": "ok", "shipment_id": ..., "events": [{ts, status, city, note, source}, ...]}.
Inputs: shipment_id (required). Returns: object
track_shipmentA
Track a shipment: current status, location, ETA vs promised delivery, carrier, vehicle and recent events.
Use this first whenever the user mentions a specific shipment or order.
Args:
shipment_id: Shipment ID such as "SHP-1001" (also accepts "shp1001" or "1001").
Returns:
The shipment (status, priority, origin_city, destination_city, last_city, eta, promised_by,
is_late, delay_hours, hours_to_promise, carrier_name, vehicle, customer, weight_kg, notes)
plus ``recent_events`` (latest 5, newest last). On a miss: status="error" with suggestions.
Inputs: shipment_id (required). Returns: object
update_shipment_statusA
Change a shipment's status and log a history event (e.g. mark delayed, delivered, exception).
Args:
shipment_id: Shipment ID such as "SHP-1002".
status: New status: created, picked_up, in_transit, delayed, out_for_delivery, delivered or exception.
city: Optional city where the update happened (defaults to the current/destination city).
note: Short human-readable reason, e.g. "Rain on NH-48, 6h delay". Stored as the shipment note.
Returns:
{"status": "ok", "previous_status": ..., "shipment": {...}, "event": {...}} or an error with valid values.
Inputs: status (required), shipment_id (required), city, note. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 11 tools
Tools are cleanly separated by resource and action: shipment tracking/list/history/status update, inventory/warehouses/reorders, fleet assignment, carriers, and KPIs. Overlaps are minimal; track_shipment and shipment_history differ in scope (current status plus recent events vs full event trail).
Names are consistently snake_case and mostly follow a verb_noun pattern such as track_shipment, list_shipments, update_shipment_status, check_inventory, create_reorder, assign_vehicle, and get_kpis. The main deviation is shipment_history, which is noun_noun rather than action-first, but it remains readable and predictable.
11 tools is well-scoped for a logistics control tower, covering shipments, inventory, warehouses, fleet, carriers, and KPIs without obvious filler. Each tool maps to a clear operational task.
Core operational workflows are covered: track/update shipments, inspect inventory, raise reorders, assign vehicles, and monitor KPIs. Gaps remain around shipment creation/cancellation and purchase-order or vehicle lifecycle management, but these are minor for a monitoring and dispatch-oriented server.
Maintenance
Related MCP Connectors
India shipping for AI agents: Shiprocket courier serviceability, create orders, track AWB.
AI-ready GIS, geofencing, DataSynch, CRM, inventory, routing, APIs, telemetry and workflows.
AI-native platform: cybernetic freight agents transact, verify, find services. Get verified leads.
Supply chain operations: dock scheduling, check-in, doors, inventory, orders and freight.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceProvides supply chain and shipping tools including shipment tracking, route optimization, warehouse inventory management, delivery ETA estimation, and customs documentation. Enables logistics operations through natural language interactions with Claude.8 npm36 PyPI1MIT
- FlicenseAqualityCmaintenanceEnables AI agents to query orders, manage routes, track drivers, and analyze delivery performance on the FleetSync last-mile delivery platform through natural language.18-
- AlicenseNot gradedqualityBmaintenanceProvides real-time freight tracking and load visibility for logistics and AI agents: create loads, get live GPS positions, trip stats, and confirm deliveries via geofenced statuses.1MIT
- FlicenseNot gradedqualityBmaintenanceEnables agent-friendly warehouse operations including inventory search and adjustment, dock booking and cancellation, exception creation and resolution, with site-based access control preventing cross-site access.-