Upper Route Planner MCP by usefulapi

Read Upper drivers and stops; create and optimize routes, assign drivers, share routes to the app.

使うべきか

品質と安全性

A
説明の品質
97%
スキーマの完全性
81%
命名の品質
80%
ポイズニングのリスク
100%
権限の一致
100%
プロトコルへの準拠
100%

ツール定義とプロトコルへの準拠に関する自動分析に基づいています。

コンテキストコスト

~4,049トークン数(ツール定義)
~2.7 KB一般的なレスポンスサイズ
注意への影響は大きい(128k コンテキストの 3.16%)

これは、サーバーのツールがモデルのコンテキストに読み込まれるたびに消費されるおおよそのトークン数です。数が多いほど、ほかのタスクに使える注意が減ります。

インストール

ワンクリックインストール

これを `claude_desktop_config.json` ファイルに追加してください:

{
  "mcpServers": {
    "upper-route-planner": {
      "url": "https://upper-route-planner.usefulapi.io/mcp"
    }
  }
}

リモートエンドポイント

https://upper-route-planner.usefulapi.io/mcpstreamable-http

できること

ツール一覧

ツール(12)

🟢 読み取り専用🟡 書き込み🔴 削除⚪ 不明
🟢upper_list_drivers

List the active drivers on the Upper team that owns the API token: id, name, email and phone. Use the ids with upper_assign_drivers and upper_share_route_to_drivers. GET /ext-get-drivers.

入力スキーマ

{
  "type": "object",
  "properties": {},
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢upper_list_stops(route_id, scheduled, unscheduled, limit, offset)

List the team's stops in optimized order: address, coordinates, contact, time window, duration, status, route_id and custom ids. Pass route_id for one route (optionally scheduled=true/false); pass unscheduled=true (without route_id) for stops not on any route; with no filter all active stops are returned. Upper has no paging, so this tool pages locally: `limit` stops (default 100, max 500) starting at `offset`; the reply says if more remain (truncated, next_offset). GET /ext-get-stops.

入力スキーマ

{
  "type": "object",
  "properties": {
    "route_id": {
      "description": "Only the stops on this route.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "scheduled": {
      "description": "With route_id only: true = scheduled stops, false = unscheduled stops of that route.",
      "type": "boolean"
    },
    "unscheduled": {
      "description": "Without route_id: true = unscheduled stops across all routes.",
      "type": "boolean"
    },
    "limit": {
      "description": "Most stops to return, 1-500 (default 100).",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 500
    },
    "offset": {
      "description": "Skip this many stops (use next_offset from the previous reply to read on).",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢upper_get_optimization_status(route_id)

Check whether a route is optimized: status is optimized, pending (still running) or not_optimized, plus the queue_id of the last job. Poll this after upper_optimize_route. GET /ext-optimization-status.

入力スキーマ

{
  "type": "object",
  "properties": {
    "route_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The route id."
    }
  },
  "required": [
    "route_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢upper_get_custom_fields

The workspace's five stop custom-field slots (custom1 - custom5: type, label, enabled, required) and which are enabled. Needs the Custom fields feature in the Upper plan. GET /ext-get-custom-fields.

入力スキーマ

{
  "type": "object",
  "properties": {},
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢upper_get_capacity_fields

The workspace's five capacity-field slots (capacity1 - capacity5: label, unit, enabled) used for load planning. GET /ext-get-capacity-fields.

入力スキーマ

{
  "type": "object",
  "properties": {},
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟡upper_create_route(route_name, route_date, optimize_for, units, pickup_settings, ...)

WRITE: create a new, empty route (name, date, optimization preference, units, pickup sequencing, service time). Omitted settings fall back to the account's defaults. Returns the new route_id; add stops with upper_create_stop. Calling it twice creates two routes. POST /ext-create-route.

入力スキーマ

{
  "type": "object",
  "properties": {
    "route_name": {
      "description": "Route name (default: New Route).",
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "route_date": {
      "description": "Route start date, yyyy-mm-dd (default today).",
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "optimize_for": {
      "description": "Optimize for time or distance.",
      "type": "string",
      "enum": [
        "time",
        "distance"
      ]
    },
    "units": {
      "description": "Distance units: miles or km.",
      "type": "string",
      "enum": [
        "miles",
        "km"
      ]
    },
    "pickup_settings": {
      "description": "When pickups are sequenced: auto, before or after the deliveries.",
      "type": "string",
      "enum": [
        "auto",
        "before",
        "after"
      ]
    },
    "service_time": {
      "type": "integer",
      "minimum": 0,
      "maximum": 86400,
      "description": "Per-stop service (dwell) time in seconds."
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴upper_update_route(route_id, route_name, route_date, optimize_for, units, ...)

WRITE: change settings of an existing route (name, date, optimize_for, units, pickup_settings, service_time). Only the fields you pass change. POST /ext-update-route.

入力スキーマ

{
  "type": "object",
  "properties": {
    "route_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The route to update."
    },
    "route_name": {
      "description": "New route name.",
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "route_date": {
      "description": "New start date, yyyy-mm-dd.",
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "optimize_for": {
      "description": "Optimize for time or distance.",
      "type": "string",
      "enum": [
        "time",
        "distance"
      ]
    },
    "units": {
      "description": "Distance units: miles or km.",
      "type": "string",
      "enum": [
        "miles",
        "km"
      ]
    },
    "pickup_settings": {
      "description": "When pickups are sequenced: auto, before or after.",
      "type": "string",
      "enum": [
        "auto",
        "before",
        "after"
      ]
    },
    "service_time": {
      "type": "integer",
      "minimum": 0,
      "maximum": 86400,
      "description": "Per-stop service (dwell) time in seconds."
    }
  },
  "required": [
    "route_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟡upper_create_stop(address, route_id, city, state, zipcode, ...)

WRITE: create a stop. The address is geocoded by Upper. Pass route_id to put it on a route (the route must not be active/in progress; an optimized route is flagged for re-optimization); omit it for an unscheduled stop. Calling it twice creates two stops. POST /ext-create-stop.

入力スキーマ

{
  "type": "object",
  "properties": {
    "address": {
      "type": "string",
      "minLength": 1,
      "maxLength": 500,
      "description": "Street address of the stop (geocoded by Upper)."
    },
    "route_id": {
      "description": "Route to attach the stop to; omit for an unscheduled stop.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "city": {
      "description": "City (overrides the geocoded value).",
      "type": "string",
      "maxLength": 200
    },
    "state": {
      "description": "State or region (overrides the geocoded value).",
      "type": "string",
      "maxLength": 200
    },
    "zipcode": {
      "description": "Postal code (overrides the geocoded value).",
      "type": "string",
      "maxLength": 40
    },
    "contact_name": {
      "description": "Contact (recipient) name.",
      "type": "string",
      "maxLength": 200
    },
    "phone": {
      "description": "Contact phone number; non-digits are stripped by Upper.",
      "type": "string",
      "maxLength": 40
    },
    "phone_country_code": {
      "description": "Phone dialing code, for example 1.",
      "type": "string",
      "pattern": "^\\d{1,4}$"
    },
    "email": {
      "description": "Contact email.",
      "type": "string",
      "maxLength": 254
    },
    "note": {
      "description": "Free-text note shown to the driver.",
      "type": "string",
      "maxLength": 2000
    },
    "company_name": {
      "description": "Company name for the stop.",
      "type": "string",
      "maxLength": 200
    },
    "nick_name": {
      "description": "Short label for the stop.",
      "type": "string",
      "maxLength": 100
    },
    "pin_color": {
      "description": "Map pin colour, hex like #FF6600.",
      "type": "string",
      "pattern": "^#[0-9a-fA-F]{6}$"
    },
    "start_time": {
      "description": "Earliest service time (time window start), HH:MM or HH:MM:SS.",
      "type": "string",
      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d)?$"
    },
    "end_time": {
      "description": "Latest service time (time window end), HH:MM or HH:MM:SS.",
      "type": "string",
      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d)?$"
    },
    "stop_duration": {
      "description": "Service duration at the stop, in seconds.",
      "type": "integer",
      "minimum": 0,
      "maximum": 86400
    },
    "stop_type": {
      "description": "Stop type, for example Delivery or Pickup.",
      "type": "string",
      "maxLength": 50
    },
    "stop_priority": {
      "description": "Stop priority, for example Normal, High, Urgent.",
      "type": "string",
      "maxLength": 50
    },
    "parcel_count": {
      "description": "Number of parcels at the stop.",
      "type": "integer",
      "minimum": 0,
      "maximum": 100000
    },
    "customer_system_id": {
      "description": "Your own identifier for the stop (for cross-referencing).",
      "type": "string",
      "maxLength": 200
    },
    "custom_fields": {
      "type": "object",
      "propertyNames": {
        "type": "string",
        "minLength": 1,
        "maxLength": 64
      },
      "additionalProperties": {
        "anyOf": [
          {
            "type": "string",
            "maxLength": 2000
          },
          {
            "type": "number"
          },
          {
            "type": "boolean"
          }
        ]
      },
      "description": "Custom field values keyed by slot (custom1 - custom5). Only fields enabled in the workspace (and in the plan) are stored."
    },
    "capacity_fields": {
      "type": "object",
      "properties": {
        "capacity1": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "capacity2": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "capacity3": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "capacity4": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "capacity5": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        }
      },
      "description": "Capacity values (integers) for load planning, keys capacity1 - capacity5."
    }
  },
  "required": [
    "address"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴upper_update_stop(stop_id, address, route_id, city, state, ...)

WRITE: change an existing stop; only the fields you pass change. A new address is re-geocoded (city/state/zipcode you pass with it are ignored); city/state/zipcode apply only without an address. Passing route_id moves the stop to that route. Editing a stop on an optimized route flags the route for re-optimization; stops on an active route cannot be edited. POST /ext-update-stop.

入力スキーマ

{
  "type": "object",
  "properties": {
    "stop_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The stop to update."
    },
    "address": {
      "description": "New street address (re-geocoded).",
      "type": "string",
      "minLength": 1,
      "maxLength": 500
    },
    "route_id": {
      "description": "Move the stop to this route.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "city": {
      "description": "City (only used when no address is passed).",
      "type": "string",
      "maxLength": 200
    },
    "state": {
      "description": "State or region (only used when no address is passed).",
      "type": "string",
      "maxLength": 200
    },
    "zipcode": {
      "description": "Postal code (only used when no address is passed).",
      "type": "string",
      "maxLength": 40
    },
    "contact_name": {
      "description": "Contact (recipient) name.",
      "type": "string",
      "maxLength": 200
    },
    "phone": {
      "description": "Contact phone number; non-digits are stripped by Upper.",
      "type": "string",
      "maxLength": 40
    },
    "phone_country_code": {
      "description": "Phone dialing code, for example 1.",
      "type": "string",
      "pattern": "^\\d{1,4}$"
    },
    "email": {
      "description": "Contact email.",
      "type": "string",
      "maxLength": 254
    },
    "note": {
      "description": "Free-text note shown to the driver.",
      "type": "string",
      "maxLength": 2000
    },
    "company_name": {
      "description": "Company name for the stop.",
      "type": "string",
      "maxLength": 200
    },
    "nick_name": {
      "description": "Short label for the stop.",
      "type": "string",
      "maxLength": 100
    },
    "pin_color": {
      "description": "Map pin colour, hex like #FF6600.",
      "type": "string",
      "pattern": "^#[0-9a-fA-F]{6}$"
    },
    "start_time": {
      "description": "Earliest service time (time window start), HH:MM or HH:MM:SS.",
      "type": "string",
      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d)?$"
    },
    "end_time": {
      "description": "Latest service time (time window end), HH:MM or HH:MM:SS.",
      "type": "string",
      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d)?$"
    },
    "stop_duration": {
      "description": "Service duration at the stop, in seconds.",
      "type": "integer",
      "minimum": 0,
      "maximum": 86400
    },
    "stop_type": {
      "description": "Stop type, for example Delivery or Pickup.",
      "type": "string",
      "maxLength": 50
    },
    "stop_priority": {
      "description": "Stop priority, for example Normal, High, Urgent.",
      "type": "string",
      "maxLength": 50
    },
    "parcel_count": {
      "description": "Number of parcels at the stop.",
      "type": "integer",
      "minimum": 0,
      "maximum": 100000
    },
    "customer_system_id": {
      "description": "Your own identifier for the stop (for cross-referencing).",
      "type": "string",
      "maxLength": 200
    },
    "custom_fields": {
      "type": "object",
      "propertyNames": {
        "type": "string",
        "minLength": 1,
        "maxLength": 64
      },
      "additionalProperties": {
        "anyOf": [
          {
            "type": "string",
            "maxLength": 2000
          },
          {
            "type": "number"
          },
          {
            "type": "boolean"
          }
        ]
      },
      "description": "Custom field values keyed by slot (custom1 - custom5). Only fields enabled in the workspace (and in the plan) are stored."
    },
    "capacity_fields": {
      "type": "object",
      "properties": {
        "capacity1": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "capacity2": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "capacity3": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "capacity4": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "capacity5": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        }
      },
      "description": "Capacity values (integers) for load planning, keys capacity1 - capacity5."
    }
  },
  "required": [
    "stop_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴upper_assign_drivers(route_id, driver_ids)

WRITE: assign one or more drivers (ids from upper_list_drivers) to a route, replacing the route's drivers. Every id must be an active driver on the team. If the route was already optimized it is reset to unoptimized (needs_optimization: true), so run upper_optimize_route again. POST /ext-assign-drivers.

入力スキーマ

{
  "type": "object",
  "properties": {
    "route_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The route."
    },
    "driver_ids": {
      "minItems": 1,
      "maxItems": 100,
      "type": "array",
      "items": {
        "type": "integer",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991
      },
      "description": "Driver ids to assign."
    }
  },
  "required": [
    "route_id",
    "driver_ids"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴upper_optimize_route(route_id, timezone)

WRITE: start optimizing a route's stop order. The route needs at least one stop and one assigned driver (upper_assign_drivers). It runs asynchronously: this returns status pending and a queue_id, then poll upper_get_optimization_status. If a job is already running, that job is returned. POST /ext-optimize-route.

入力スキーマ

{
  "type": "object",
  "properties": {
    "route_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The route to optimize."
    },
    "timezone": {
      "description": "IANA timezone for the optimization, for example America/New_York.",
      "type": "string",
      "minLength": 1,
      "maxLength": 64,
      "pattern": "^[A-Za-z0-9_+\\-/]+$"
    }
  },
  "required": [
    "route_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟡upper_share_route_to_drivers(route_id, driver_ids, timezone)

WRITE: push a route to the drivers' mobile app NOW, which sends each driver a notification. Without driver_ids the route's assigned drivers are used; with them, every id must be an active driver on the team. Sending twice notifies twice. Confirm with the user before calling. POST /ext-share-to-driver.

入力スキーマ

{
  "type": "object",
  "properties": {
    "route_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The route to share."
    },
    "driver_ids": {
      "description": "Drivers to notify (default: the route's assigned drivers).",
      "minItems": 1,
      "maxItems": 100,
      "type": "array",
      "items": {
        "type": "integer",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991
      }
    },
    "timezone": {
      "description": "IANA timezone, for example America/New_York.",
      "type": "string",
      "minLength": 1,
      "maxLength": 64,
      "pattern": "^[A-Za-z0-9_+\\-/]+$"
    }
  },
  "required": [
    "route_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}

コミュニティ

このサーバーを評価する

エビデンス

最近の観測

検証済みバージョンは記録されていませんツール 12 件