MCP server

If you work with an AI coding assistant, you can connect it to the Logistics API through our Model Context Protocol server. Your assistant can then search this documentation, read the API contract, and look up your own parcels, without you pasting anything into a chat window.

There is nothing to install. The server runs alongside the API and you authenticate with the same credentials you already use.

Connecting

Connecting takes four steps. The first three are the same ones you follow for
the rest of the API: if you already have a valid access token for the
environment you want, go straight to step 4.

1. Choose the environment

Decide first whether you connect to sandbox or to production: everything that
follows, from the credentials to the endpoint, belongs to one of them.

EnvironmentMCP endpointWhere you get the credentials
Sandboxhttps://logistics.api.cabify-sandbox.com/mcpCabify Logistics Sandbox
Productionhttps://logistics.api.cabify.com/mcpCabify Logistics

The server runs on the same host as the rest of the API and speaks MCP over
its Streamable HTTP transport, so it only answers POST.

We recommend starting with sandbox, where your assistant can only ever see
test data.

2. Get your API credentials

You need an API key for the environment you chose: a client id and a client
secret. If you do not have one yet, follow
Get an API key in that environment's portal. A key
created in one environment does not work in the other.

3. Get an access token

The server does not accept the client id and secret directly: exchange them
for an access token at the authorization endpoint, as for any other API call.

Sandbox:

curl -X POST -d "grant_type=client_credentials&client_id=<your-client-id>&client_secret=<your-client-secret>" \
  --url https://logistics.api.cabify-sandbox.com/auth/api/authorization

Production:

curl -X POST -d "grant_type=client_credentials&client_id=<your-client-id>&client_secret=<your-client-secret>" \
  --url https://logistics.api.cabify.com/auth/api/authorization

The response carries the token in access_token:

{
    "access_token": "alfanumeric_example_access_token",
    "refresh_token": "alfanumeric_example_refresh_token",
    "expires_in": 2591999,
    "token_type": "Bearer"
}

Keep it in an environment variable named after its environment, which is what
the commands in step 4 read:

export DELIVERY_API_SANDBOX_TOKEN="alfanumeric_example_access_token"
# or, for production:
export DELIVERY_API_PRODUCTION_TOKEN="alfanumeric_example_access_token"

The token expires after expires_in seconds (about 30 days). When it does,
the server answers 401 with "error": "invalid_token", and your assistant
usually shows the server as failed or disconnected: get a new token, as explained in
Getting started, and update it in your
assistant's configuration.

4. Add the server to your assistant

Add one server per environment, named after it. If you only use one
environment, add only that one; if you use both, for instance building against
sandbox and then checking real shipments in production, add both rather than
switching a single one back and forth.

With Claude Code:

claude mcp add --transport http delivery-api-sandbox https://logistics.api.cabify-sandbox.com/mcp \
  --header "Authorization: Bearer ${DELIVERY_API_SANDBOX_TOKEN}"

claude mcp add --transport http delivery-api-production https://logistics.api.cabify.com/mcp \
  --header "Authorization: Bearer ${DELIVERY_API_PRODUCTION_TOKEN}"

With any client that reads a JSON configuration, such as Cursor:

{
  "mcpServers": {
    "delivery-api-sandbox": {
      "url": "https://logistics.api.cabify-sandbox.com/mcp",
      "headers": {
        "Authorization": "Bearer <your-sandbox-access-token>"
      }
    },
    "delivery-api-production": {
      "url": "https://logistics.api.cabify.com/mcp",
      "headers": {
        "Authorization": "Bearer <your-production-access-token>"
      }
    }
  }
}

Why one server per environment:

  • You always know which environment answered. Assistants tell tools apart
    by the server they belong to, so every call names its environment, and you
    can ask for one explicitly: "check this parcel in sandbox".
  • Nothing gets out of step. The host and the token change together, so you
    cannot end up with the production host and a sandbox token, or reading one
    environment while believing it is the other.
  • Production stays a deliberate choice. The server is read-only, but in
    production your assistant reads your real shipments. Keep the production
    server disabled until you need it: most assistants let you switch a server
    off without removing it.
  • Each token expires on its own, so renewing one never breaks the other.

To check that it works, ask your assistant something like "list the hubs in
my sandbox account"
. If it cannot reach the server, try the endpoint
directly: this request should answer with the server's name and protocol
version.

curl -X POST https://logistics.api.cabify-sandbox.com/mcp \
  -H "Authorization: Bearer ${DELIVERY_API_SANDBOX_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18"}}'

A 401 means the token is wrong or expired (step 3), or that it belongs to
the other environment. A 403 means the Authorization: Bearer <token>
header did not reach the server.

What your assistant can do

Read the documentation

ToolWhat it does
search_docsSearches this documentation and the API contract.
read_docReads one page or one specification file.
list_docsLists what is available.
openapi_operationsLists the API operations.
openapi_operationShows the request and response of one operation.
error_codeExplains an error the API returned, and what to do about it.

Look up your account

ToolWhat it does
get_parcelReads one of your parcels by id.
get_parcel_by_external_idFinds your parcels by the external_id you gave them — your own order number.
track_parcelThe state timeline of one of your parcels.
search_parcelsLists your parcels in the states you ask for. At least one state is required.
list_shipping_typesThe shipping types available to you at a pickup location.
estimate_deliveryPrice and timings for a shipment, before you create it.
check_availabilityWhether anything can be shipped from a pickup point for your account, before you create anything.
get_proof_configWhich proofs of delivery are active on one of your parcels.
get_labelWhether a printable label is ready for a parcel, and where to download it.
list_webhooksThe webhook subscriptions you have configured.
list_hubsThe hubs registered under your account.
get_hubReads one of your hubs by the external id you gave it.

Work out why something fails

ToolWhat it does
diagnose_shipmentChecks what your account can ship from a pickup location and, given a parcel id, what state that parcel is in, and reports the likely cause and the next step.

This is the one to reach for when a request failed and the error alone does not
say why, because the cause is more often coverage or account configuration than
a malformed payload. It takes coordinates, not an address, and it does not
check whether a driver is free at this moment -- so a location it reports as
fine can still fail momentarily.

These are scoped to the credentials you connect with: your assistant can only ever see your own data.

What it cannot do

The server is read-only. Creating, shipping and cancelling parcels stay on the REST API, so an assistant can look up how an operation works and prepare the call, but it cannot ship anything on your behalf.

Good to know

  • The server answers one JSON-RPC message per request, or a batch of at most 20. It never initiates messages and keeps no session, so GET and DELETE on the endpoint are declined.
  • Calls count towards the same rate limits as the rest of the API.
  • If a tool fails, the reason comes back in the tool result rather than as an HTTP error, which is how MCP reports it.

Did this page help you?