renfield-mcp-tracking
by ebongard
README.md
# renfield-mcp-tracking
Multi-carrier parcel-tracking MCP server for [Renfield](https://github.com/ebongard/renfield).
Talks **directly** to carrier APIs — **no third-party aggregator** (no Shippo,
AfterShip, EasyPost, …). Your tracking data never passes through a SaaS middleman.
## Carriers
| Carrier | Backend | Notes |
|---|---|---|
| **DHL / Deutsche Post** | Shipment Tracking – Unified API | Free, **production** key. One endpoint covers DHL Paket, Express, Deutsche Post, Freight. Initial quota 250 calls/day. |
| **UPS** | OAuth client-credentials + Track API | Free developer app. |
| **FedEx** | OAuth client-credentials + Track API | Free developer app. |
| **DPD** | Web deep-link only | No free public API for private users → returns a link into `tracking.dpd.de`. |
| **Hermes** | Web deep-link only | → `myhermes.de`. |
| **GLS** | Web deep-link only | → `gls-group.com`. |
Each API adapter **self-disables** when its credentials are absent — the server
still starts, and `list_carriers()` reports which carriers are usable. The
link-only carriers always work (they only return a tracking URL). Adding real
API access for DPD/Hermes/GLS later means dropping in a `CarrierAdapter`
subclass and registering it — no other code changes.
## Tools
- **`track_parcel(tracking_number, carrier="auto")`** — primary. Returns a
normalized result: `status`, `status_description`, `estimated_delivery`,
`events` (newest first), `web_url`, `success`.
- **`list_carriers()`** — supported carriers + configured state.
- **`detect_carrier(tracking_number)`** — guess the carrier from the number
format (confident for UPS `1Z…` and DHL `JJD…`; ambiguous numeric numbers
fall back to `TRACKING_DEFAULT_CARRIER`).
### Normalized status values
`pre_transit` · `transit` · `out_for_delivery` · `delivered` · `exception` ·
`unknown` · `not_found` · `link_only` · `not_configured` · `error`
## Configuration
| Env var | Purpose |
|---|---|
| `DHL_API_KEY` | DHL Developer Portal app key (the `DHL-API-Key`). |
| `UPS_CLIENT_ID` / `UPS_CLIENT_SECRET` | UPS developer app credentials. |
| `FEDEX_CLIENT_ID` / `FEDEX_CLIENT_SECRET` | FedEx developer app credentials. |
| `TRACKING_DEFAULT_CARRIER` | Fallback when auto-detect is inconclusive (default `dhl`). |
| `DHL_TRACKING_BASE_URL` / `UPS_TRACKING_BASE_URL` / `FEDEX_TRACKING_BASE_URL` | Override API base (test environments). |
### Getting keys
- **DHL** — register at <https://developer.dhl.com/>, create an app, subscribe
it to *Shipment Tracking – Unified*, copy the key. Works against production.
- **UPS** — <https://developer.ups.com/> → create an app → OAuth client id/secret.
- **FedEx** — <https://developer.fedex.com/> → create an app → Track API.
## Run
```bash
pip install -e ".[dev]"
python -m renfield_mcp_tracking # stdio MCP server
pytest -q
```
## Use in Renfield
Installed into the backend image via `src/backend/requirements.txt` and run as a
stdio server from `config/mcp_servers.yaml` (`name: tracking`). Enable with
`TRACKING_ENABLED=true` and set whichever carrier keys you have. Tools become
available to the agent as `mcp.tracking.track_parcel` etc.
## License
MIT
TDQS
A4.5/5.0
Scored across 3 tools
Disambiguation5/5
Each tool has a distinct purpose: carrier detection, listing carriers, and tracking parcels. No overlap in functionality.
Naming Consistency5/5
All tools follow a snake_case verb_noun pattern (detect_carrier, list_carriers, track_parcel), with consistent naming. The slight pluralization in list_carriers is natural for listing operations.
Tool Count5/5
With only 3 tools, the set is concise yet sufficient for the domain of parcel tracking. Each tool earns its place without unnecessary bloat.
Completeness5/5
The tool set covers the core lifecycle: carrier detection (identify carrier from number), carrier discovery (list available carriers), and tracking (get status and events). No obvious gaps for a tracking helper server.
Maintenance
ActivityInactive
ResponsivenessNo issues