Build Shipment Tracking Tools for Your Logistics Provider

Your ops team spends half their day checking shipment statuses. One carrier has a web portal, another has a mobile app, a third only sends email updates. When a customer calls asking where their order is, someone has to figure out which carrier is handling it, log into the right system, and look it up. Multiply that by fifty shipments a day and you have a team that does nothing but check tracking portals.

This playbook walks you through building tools that wrap multiple carrier APIs behind a single interface. You will build per-carrier tracking tools, then a unified tracking tool that automatically routes to the right carrier based on the tracking number format. By the end, anyone on your team can ask "Where is shipment TRK-88421?" and get the answer without knowing or caring which carrier is handling it.

Most of this workflow happens from your AI client (Claude Desktop, ChatGPT, Cursor) through the MCP connection to Assist. The one exception is credential configuration: API keys and secrets should be entered directly in the Assist UI under the Permissions tab of each tool so they never pass through chat.

What you need before you start

  • An Assist workspace with an MCP connection configured in your AI client
  • API credentials for each carrier you use (for example, FedEx, UPS, a regional carrier)
  • The API documentation or base URLs for each carrier
  • A few real tracking numbers for each carrier that you can use for testing

Phase 1: Identify your carrier APIs

Start by telling the AI which carriers you use and what you know about their APIs.

"We ship with three carriers: FedEx, UPS, and a regional carrier called FastFreight. I need to build tracking tools for all three. FedEx uses their Track API at https://apis.fedex.com/track/v1. UPS uses their Tracking API at https://onlinetools.ups.com/api/track/v1. FastFreight has a simple REST API at https://api.fastfreight.com/v2/tracking."

Share the authentication details for each.

"FedEx uses OAuth2 -- I have a client ID and client secret. UPS uses an API key passed in the Authorization header. FastFreight uses a simple API key in an X-Api-Key header."

The AI now knows what it is working with. If you have documentation, share the relevant parts.

"FedEx Track API: POST to /track with a JSON body containing trackingInfo array with trackingNumberInfo.trackingNumber. UPS: GET /details/{tracking_number} with transId and transactionSrc headers. FastFreight: GET /tracking/{tracking_number}."

Phase 2: Build the FedEx tracking tool

Start with FedEx since it has the most complex authentication.

"Create a tool called 'logistics_track_fedex' that tracks a FedEx shipment. It takes a tracking_number string. First, it needs to get an OAuth token by posting to https://apis.fedex.com/oauth/token with grant_type=client_credentials, client_id from env var FEDEX_CLIENT_ID, and client_secret from env var FEDEX_CLIENT_SECRET. Then use that token to POST to https://apis.fedex.com/track/v1/trackingnumbers with the tracking number. Return the current status, last location, estimated delivery date, and a timeline of scan events."

The AI creates the tool. Before testing, set up the credentials.

Do not paste the client ID or secret into chat. Open the tool in the Assist UI, click the Permissions tab, and configure both:

  • Environment Variables: add FEDEX_CLIENT_ID and FEDEX_CLIENT_SECRET as custom variables. The value field is masked, and values never enter the LLM context or your chat history.
  • Network Access: add apis.fedex.com to the allowed domains.

See Managing Permissions for the step-by-step UI flow.

Now test.

"Test logistics_track_fedex with tracking_number '794644790138'."

The FedEx API returns deeply nested JSON. You will almost certainly need to refine the output parsing.

"The raw response is huge. I only need: the current status description, the last scan location (city, state), the estimated delivery date and time, and the last 5 scan events with their timestamps and locations. Clean up the response to just those fields."

"The timestamps are in a weird format. Convert them to ISO 8601."

"Test again. That looks right. But add the service type (Ground, Express, etc.) to the response so we know what speed the shipment is moving at."

Phase 3: Build the UPS tracking tool

Now build the UPS tool. This one is simpler since it uses API key auth.

"Create a tool called 'logistics_track_ups' that tracks a UPS shipment. It takes a tracking_number string. Call GET https://onlinetools.ups.com/api/track/v1/details/{tracking_number} with Authorization header 'Bearer {UPS_API_KEY}' from env var, plus transId and transactionSrc headers. Return the same fields as the FedEx tool: current status, last location, estimated delivery, service type, and last 5 scan events."

In the Assist UI, open this tool's Permissions tab and add UPS_API_KEY as an environment variable (masked input) and onlinetools.ups.com to the network access list.

"Test logistics_track_ups with tracking_number '1Z999AA10123456784'."

Review the output and make it consistent with the FedEx tool.

"The status field says 'In Transit' for FedEx but 'On the Way' for UPS. Normalize the status values across carriers. Use a standard set: 'Picked Up', 'In Transit', 'Out for Delivery', 'Delivered', 'Exception', 'Unknown'."

"The location format is different too. FedEx returns city and state separately, UPS returns a single string. Make both tools return location as an object with city, state, and country fields."

Consistency matters. Your unified tool will combine results from all carriers, and the output format needs to be the same regardless of which carrier handled the shipment.

Phase 4: Build the FastFreight tracking tool

The regional carrier's API is usually the simplest.

"Create a tool called 'logistics_track_fastfreight' that tracks a FastFreight shipment. It takes a tracking_number string. Call GET https://api.fastfreight.com/v2/tracking/{tracking_number} with X-Api-Key header from env var FASTFREIGHT_API_KEY. Return the same normalized fields: current status, last location, estimated delivery, service type, and last 5 events."

In the Permissions tab for this tool, add FASTFREIGHT_API_KEY as an environment variable and api.fastfreight.com to the network access list.

"Test logistics_track_fastfreight with tracking_number 'FF-20240315-8842'."

"The status values from FastFreight are different again -- they use 'MOVING', 'AT_DESTINATION', 'COMPLETE'. Map those to the same standard set we defined for FedEx and UPS."

"FastFreight doesn't return estimated delivery time, only date. Set the time to null when it's not available instead of making one up."

Phase 5: Build the unified tracking tool

Now build the tool your team will actually use. It takes any tracking number, figures out which carrier it belongs to, and calls the right tracking tool.

"Create a tool called 'logistics_track_shipment' that takes a tracking_number string. It should determine the carrier from the tracking number format and then call the appropriate tracking function. FedEx tracking numbers are 12-15 digits. UPS tracking numbers start with '1Z' followed by alphanumeric characters. FastFreight tracking numbers start with 'FF-'. If the format doesn't match any known carrier, return an error saying the carrier could not be identified."

The AI will write a routing function that inspects the tracking number and delegates to the right carrier's API call. Importantly, it should inline the API calls rather than calling the other tools -- this keeps it self-contained.

"Test logistics_track_shipment with a FedEx number '794644790138'."

"Now test with a UPS number '1Z999AA10123456784'."

"Now test with a FastFreight number 'FF-20240315-8842'."

"Now test with a tracking number that doesn't match any pattern, like 'XYZ123'. It should return a clear error."

You might discover edge cases in the routing logic.

"Some of our FedEx numbers are exactly 12 digits and some are 15. Make sure the regex handles both. Also, we sometimes get FedEx door tags that start with 'DT' -- add that as a FedEx pattern too."

"We also use FedEx SmartPost for some shipments. Those tracking numbers are 22 digits starting with '61'. Add that pattern."

Iterate until the routing covers all your real tracking numbers.

Phase 6: Add estimated delivery calculation

The ops team needs to know not just the estimated delivery date but whether a shipment is on time, early, or late relative to the promise made to the customer.

"Update logistics_track_shipment to accept an optional promised_delivery_date parameter (ISO 8601 date). If provided, add a 'delivery_status' field that says 'on_time' if the estimated delivery is on or before the promised date, 'at_risk' if the estimated delivery is within 1 day of the promised date, and 'late' if the estimated delivery is after the promised date. If the shipment is already delivered, compare the actual delivery date to the promised date."

"Test with a shipment that has an estimated delivery of tomorrow and a promised date of today. It should show 'late'."

"Test with a shipment that's already delivered. Does it compare the actual delivery date correctly?"

"The at_risk window should be configurable. Change it so if the promised date is more than 3 days away, at_risk means within 2 days. If the promised date is 3 or fewer days away, at_risk means within 1 day."

Phase 7: Configure all API keys

You have been setting API keys on individual tools. Review the configuration in the Assist UI to make sure everything is consistent and uses workspace-level credentials where possible.

"List all the environment variables configured across the logistics tracking tools. Are there any that are missing or misconfigured?"

The AI can tell you which variables each tool expects, but the values themselves are only managed through the Permissions tab. If any tool's code references an env var that is not configured, open that tool's Permissions tab and add it there.

If your workspace has connections configured for these carriers, prefer linking to them rather than entering raw values. In each tool's Permissions tab, use the From Connection option when adding an environment variable:

  • Link FEDEX_CLIENT_ID and FEDEX_CLIENT_SECRET to the fields of the "FedEx Production" connection.
  • Link UPS_API_KEY to the "UPS Production" connection.
  • Link FASTFREIGHT_API_KEY to the "FastFreight" connection.

Connection-linked variables resolve at runtime, so rotating a credential in one place updates every tool that uses it.

Phase 8: Test with real tracking numbers

Before publishing, test with real shipments your team is currently tracking.

"Here are five real tracking numbers from shipments we're currently managing. Track each one and tell me the status: [number1], [number2], [number3], [number4], [number5]."

The AI will call logistics_track_shipment for each one. Review the results against what you see in each carrier's portal.

"The status for [number3] shows 'In Transit' but the FedEx portal shows 'Out for Delivery'. Is the tool reading the right status field?"

"The estimated delivery for [number5] is missing. The FastFreight API sometimes returns the delivery estimate in a different field for LTL shipments. Can you check the raw response and fix the parsing?"

This is where you catch the real-world issues that do not show up in testing with sample data.

Phase 9: Commit and publish

When everything is verified against real data, commit and publish.

"Commit and publish logistics_track_fedex with the message 'FedEx shipment tracking with normalized status and event timeline'."

"Commit and publish logistics_track_ups with the message 'UPS shipment tracking with normalized status and event timeline'."

"Commit and publish logistics_track_fastfreight with the message 'FastFreight shipment tracking with normalized status and event timeline'."

"Commit and publish logistics_track_shipment with the message 'Unified shipment tracking across FedEx, UPS, and FastFreight with automatic carrier detection and delivery status calculation'."

What you built

  • logistics_track_fedex -- Tracks FedEx shipments with OAuth2 authentication and normalized output
  • logistics_track_ups -- Tracks UPS shipments with normalized status and location format
  • logistics_track_fastfreight -- Tracks FastFreight shipments with status mapping to standard values
  • logistics_track_shipment -- Unified tracking tool that auto-detects the carrier from the tracking number and returns a consistent response with optional delivery status calculation

Your ops team no longer needs to know which carrier is handling a shipment or how to log into three different portals. They ask their AI client to track a shipment and get the answer. If they give you more carriers, you add another per-carrier tool and update the routing logic. The unified interface stays the same.

Related guides