Driversnote MCP
Connect an AI assistant to your Driversnote trips, reports, vehicles, workplaces and teams.
Authentication
Add https://mcp.driversnote.com to an OAuth-capable MCP client using Streamable HTTP, then sign in to Driversnote and approve access. The MCP endpoint is /.
OAuth access is available to free and paid accounts. The full_access scope grants read and write access to the public API as you, subject to your account and team permissions. There is no read-only OAuth scope.
- Discover. A request without a bearer token receives
401with aWWW-Authenticateheader pointing to protected resource metadata. This identifies the resource URL, authorization server and scope. - Sign in and consent. The client reads authorization server metadata, registers at
https://www.driversnote.com/oauth/registerif needed, and starts the authorization-code flow athttps://www.driversnote.com/oauth/authorizewith PKCE (S256), scopefull_accessandresource=https://mcp.driversnote.com. Sign-in and consent happen on Driversnote, not this server. - Exchange and refresh. The client handles its callback and exchanges the code and PKCE verifier at
https://www.driversnote.com/oauth/token. It owns token storage and refresh. The resource URL must also be supplied during code exchange and refresh. These OAuth endpoints live on the authorization server. - Call MCP. Send
Authorization: Bearer <access_token>on every MCP request, including initialization and tool discovery. This server checks the token athttps://www.driversnote.com/oauth/introspecton every request, then forwards it on tool calls to the Driversnote GraphQL API. The API validates expiry, revocation, resource binding and scope. The MCP server is stateless and does not persist user credentials.
Invalid tokens return 401 with error="invalid_token" in the challenge. An unavailable authorization service returns 503, not an invalid-token response.
Tool specification
These 16 specifications come from the same registration and tools/list response as the running server. Expand a tool for its description, then its full JSON specification for input/output schemas, required fields, defaults and annotations.
Use tools/list to discover tools and tools/call to invoke one after MCP initialization. For example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": { "name": "list_vehicles", "arguments": {} }
}
Successful tools return JSON in structuredContent and a text mirror. List results contain items and pagination (total, returned, hasMore, nextCursor); pass nextCursor as after to continue. Tool execution errors set isError: true with an actionable text message. Review write operations before approving them.
get_account_context — read
Get account context
Bootstrap tool: fetch a compact overview of the account behind the API key in ONE request — vehicles (with country, distance unit km/mi, and currency), organisations (what the end user calls "workplaces"), teams the user belongs to (with their own role and name on each team), and the available reimbursement methods. Call this FIRST in a session. It gives you every ID you need for the other tools (vehicleId, organisationId, teamId, countryId, vehicleTypeId) plus the units and currency to interpret distances and amounts — while spending only one request of the monthly quota. Returns flat arrays: `vehicles`, `organisations` (call these "workplaces" when talking to the user), `teams` and `reimbursementMethods`. Notes: - The API key impersonates one user; each team's `currentMemberRole` (e.g. 'admin', 'manager' or 'member') is the closest the public API gets to 'who am I'. - If a list may exceed the built-in page sizes (25 vehicles/organisations, 10 teams), follow up with the dedicated list tools.
Full tool specification (JSON)
{
"name": "get_account_context",
"title": "Get account context",
"description": "Bootstrap tool: fetch a compact overview of the account behind the API key in ONE request — vehicles (with country, distance unit km/mi, and currency), organisations (what the end user calls \"workplaces\"), teams the user belongs to (with their own role and name on each team), and the available reimbursement methods.\n\nCall this FIRST in a session. It gives you every ID you need for the other tools (vehicleId, organisationId, teamId, countryId, vehicleTypeId) plus the units and currency to interpret distances and amounts — while spending only one request of the monthly quota.\n\nReturns flat arrays: `vehicles`, `organisations` (call these \"workplaces\" when talking to the user), `teams` and `reimbursementMethods`.\n\nNotes:\n- The API key impersonates one user; each team's `currentMemberRole` (e.g. 'admin', 'manager' or 'member') is the closest the public API gets to 'who am I'.\n- If a list may exceed the built-in page sizes (25 vehicles/organisations, 10 teams), follow up with the dedicated list tools.",
"inputSchema": {
"type": "object",
"properties": {},
"$schema": "http://json-schema.org/draft-07/schema#"
},
"outputSchema": {
"type": "object",
"properties": {
"vehicles": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": [
"string",
"null"
]
},
"name": {
"$ref": "#/properties/vehicles/items/properties/id"
},
"licensePlate": {
"$ref": "#/properties/vehicles/items/properties/id"
},
"isArchived": {
"type": [
"boolean",
"null"
]
},
"vehicleTypeId": {
"$ref": "#/properties/vehicles/items/properties/id"
},
"vehicleTypeName": {
"$ref": "#/properties/vehicles/items/properties/id"
},
"countryId": {
"$ref": "#/properties/vehicles/items/properties/id"
},
"countryName": {
"$ref": "#/properties/vehicles/items/properties/id"
},
"distanceUnit": {
"$ref": "#/properties/vehicles/items/properties/id",
"description": "'km' or 'mi'"
},
"currency": {
"$ref": "#/properties/vehicles/items/properties/id"
}
},
"additionalProperties": false
}
},
"organisations": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"$ref": "#/properties/vehicles/items/properties/id"
},
"name": {
"$ref": "#/properties/vehicles/items/properties/id"
},
"isArchived": {
"$ref": "#/properties/vehicles/items/properties/isArchived"
},
"reimbursementMethodValue": {
"$ref": "#/properties/vehicles/items/properties/id"
}
},
"additionalProperties": false
}
},
"teams": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"$ref": "#/properties/vehicles/items/properties/id"
},
"name": {
"$ref": "#/properties/vehicles/items/properties/id"
},
"currentMemberId": {
"$ref": "#/properties/vehicles/items/properties/id"
},
"currentMemberRole": {
"$ref": "#/properties/vehicles/items/properties/id",
"description": "e.g. 'admin', 'manager' or 'member'"
},
"currentMemberName": {
"$ref": "#/properties/vehicles/items/properties/id"
}
},
"additionalProperties": false
}
},
"reimbursementMethods": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"$ref": "#/properties/vehicles/items/properties/id"
},
"name": {
"$ref": "#/properties/vehicles/items/properties/id"
},
"default": {
"$ref": "#/properties/vehicles/items/properties/isArchived"
}
},
"additionalProperties": false
}
}
},
"required": [
"vehicles",
"organisations",
"teams",
"reimbursementMethods"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"annotations": {
"title": "Get account context",
"readOnlyHint": true,
"destructiveHint": false,
"openWorldHint": false
},
"execution": {
"taskSupport": "forbidden"
}
}
list_trips — read
List trips
List the user's trips (mileage records) in a date range. Each trip answers: WHEN (`startAt`/`stopAt`), WHERE (`startLocationName`/`startLocationAddress` and `stopLocationName`/`stopLocationAddress` for saved locations, otherwise the free-text `startLocationPlaceholder`/`stopLocationPlaceholder`), HOW FAR (`distance`), WHAT IT IS WORTH (`amount`) and WHICH KIND (`tripType`: business/private/…). These are the attributes that matter for nearly every question — start there. Use this to answer 'how many business km did I drive in Q2?' (sum `distance`), 'where did I drive on the 12th?', to find unclassified trips (`reviewStatus` 'pending' = still needs review), or to look up trip IDs before classifying them with classify_trips. Notes: - `startDate`/`endDate` are required ISO dates, e.g. { "startDate": "2026-04-01", "endDate": "2026-06-30" }. - `fields` controls how much each row carries. 'essential' (default) = id, startAt, stopAt, the location fields, distance, amount, tripType, reviewStatus, comment — enough for almost everything and cheapest in tokens. 'full' adds odometer readings, routeOrigin, vehicle, workplace (organisation), tags and the trip type's display name — ask for it only when a question needs those. - `distance` is an integer in the vehicle's local base unit: meters in km countries (23400 = 23.4 km), miles in mile countries (check distanceUnit via get_account_context). - `amount` is the reimbursement value in the workplace's currency. - `reviewStatus` is one of: not_ready, pending, done. - Filter by `tripType` (business, private, medicalOrMoving or charitable), `vehicleId`, or `organisationId` (a workplace). - `summary.count` is the total number of matching trips across all pages. `summary.distanceSum`/`amountSum` cover only the trips returned so far; when `summary.complete` is true this page holds every match and the sums are final, otherwise keep paging with `pagination.nextCursor` and add up the sums yourself. - Paginate with `first`/`after` using `pagination.nextCursor`; keep pages large (e.g. first: 100) to conserve the 2,000 requests/month API quota.
Full tool specification (JSON)
{
"name": "list_trips",
"title": "List trips",
"description": "List the user's trips (mileage records) in a date range. Each trip answers: WHEN (`startAt`/`stopAt`), WHERE (`startLocationName`/`startLocationAddress` and `stopLocationName`/`stopLocationAddress` for saved locations, otherwise the free-text `startLocationPlaceholder`/`stopLocationPlaceholder`), HOW FAR (`distance`), WHAT IT IS WORTH (`amount`) and WHICH KIND (`tripType`: business/private/…). These are the attributes that matter for nearly every question — start there.\n\nUse this to answer 'how many business km did I drive in Q2?' (sum `distance`), 'where did I drive on the 12th?', to find unclassified trips (`reviewStatus` 'pending' = still needs review), or to look up trip IDs before classifying them with classify_trips.\n\nNotes:\n- `startDate`/`endDate` are required ISO dates, e.g. { \"startDate\": \"2026-04-01\", \"endDate\": \"2026-06-30\" }.\n- `fields` controls how much each row carries. 'essential' (default) = id, startAt, stopAt, the location fields, distance, amount, tripType, reviewStatus, comment — enough for almost everything and cheapest in tokens. 'full' adds odometer readings, routeOrigin, vehicle, workplace (organisation), tags and the trip type's display name — ask for it only when a question needs those.\n- `distance` is an integer in the vehicle's local base unit: meters in km countries (23400 = 23.4 km), miles in mile countries (check distanceUnit via get_account_context).\n- `amount` is the reimbursement value in the workplace's currency.\n- `reviewStatus` is one of: not_ready, pending, done.\n- Filter by `tripType` (business, private, medicalOrMoving or charitable), `vehicleId`, or `organisationId` (a workplace).\n- `summary.count` is the total number of matching trips across all pages. `summary.distanceSum`/`amountSum` cover only the trips returned so far; when `summary.complete` is true this page holds every match and the sums are final, otherwise keep paging with `pagination.nextCursor` and add up the sums yourself.\n- Paginate with `first`/`after` using `pagination.nextCursor`; keep pages large (e.g. first: 100) to conserve the 2,000 requests/month API quota.",
"inputSchema": {
"type": "object",
"properties": {
"startDate": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Earliest trip date to include (inclusive), e.g. 2026-04-01"
},
"endDate": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Latest trip date to include (inclusive), e.g. 2026-06-30"
},
"tripType": {
"type": "string",
"enum": [
"business",
"private",
"medicalOrMoving",
"charitable"
],
"description": "Filter by trip type: business, private, medicalOrMoving or charitable"
},
"vehicleId": {
"type": "string",
"description": "Filter by vehicle ID (see list_vehicles)"
},
"organisationId": {
"type": "string",
"description": "Filter by workplace/organisation ID (see list_organisations)"
},
"fields": {
"type": "string",
"enum": [
"essential",
"full"
],
"description": "'essential' (default): when, where, distance, amount, trip type, review status. 'full': also odometer readings, vehicle, workplace, tags."
},
"first": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"description": "Number of items to return (page size). Defaults to 50."
},
"after": {
"type": "string",
"description": "Opaque pagination cursor. Pass the `pagination.nextCursor` from a previous response to fetch the next page."
}
},
"required": [
"startDate",
"endDate"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"outputSchema": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": [
"string",
"null"
]
},
"startAt": {
"$ref": "#/properties/items/items/properties/id"
},
"stopAt": {
"$ref": "#/properties/items/items/properties/id"
},
"distance": {
"type": [
"number",
"null"
],
"description": "Integer in the vehicle's local base unit: meters in km countries, miles in mile countries"
},
"amount": {
"$ref": "#/properties/items/items/properties/distance",
"description": "Reimbursement value in the workplace's currency"
},
"comment": {
"$ref": "#/properties/items/items/properties/id"
},
"reviewStatus": {
"$ref": "#/properties/items/items/properties/id",
"description": "One of: not_ready, pending, done"
},
"routeOrigin": {
"$ref": "#/properties/items/items/properties/id"
},
"startLocationPlaceholder": {
"$ref": "#/properties/items/items/properties/id"
},
"stopLocationPlaceholder": {
"$ref": "#/properties/items/items/properties/id"
},
"startOdometerReading": {
"anyOf": [
{
"type": [
"string",
"number"
]
},
{
"type": "null"
}
]
},
"stopOdometerReading": {
"$ref": "#/properties/items/items/properties/startOdometerReading"
},
"startLocationId": {
"$ref": "#/properties/items/items/properties/id"
},
"startLocationName": {
"$ref": "#/properties/items/items/properties/id"
},
"startLocationAddress": {
"$ref": "#/properties/items/items/properties/id"
},
"stopLocationId": {
"$ref": "#/properties/items/items/properties/id"
},
"stopLocationName": {
"$ref": "#/properties/items/items/properties/id"
},
"stopLocationAddress": {
"$ref": "#/properties/items/items/properties/id"
},
"tripType": {
"$ref": "#/properties/items/items/properties/id",
"description": "One of: business, private, medicalOrMoving, charitable"
},
"tripTypeName": {
"$ref": "#/properties/items/items/properties/id"
},
"organisationId": {
"$ref": "#/properties/items/items/properties/id"
},
"organisationName": {
"$ref": "#/properties/items/items/properties/id"
},
"vehicleId": {
"$ref": "#/properties/items/items/properties/id"
},
"vehicleName": {
"$ref": "#/properties/items/items/properties/id"
},
"tags": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"$ref": "#/properties/items/items/properties/id"
},
"name": {
"$ref": "#/properties/items/items/properties/id"
}
},
"additionalProperties": false
}
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
}
},
"pagination": {
"type": "object",
"properties": {
"total": {
"type": "integer"
},
"returned": {
"type": "integer"
},
"hasMore": {
"type": "boolean"
},
"nextCursor": {
"type": [
"string",
"null"
]
}
},
"required": [
"total",
"returned",
"hasMore",
"nextCursor"
],
"additionalProperties": false,
"description": "Pagination. `total` = matching items across ALL pages (use it to answer 'how many'); `returned` = items in this page; pass `nextCursor` back as the `after` input to fetch the next page (null when `hasMore` is false)."
},
"summary": {
"type": "object",
"properties": {
"count": {
"$ref": "#/properties/items/items/properties/distance"
},
"distanceSum": {
"$ref": "#/properties/summary/properties/count"
},
"amountSum": {
"$ref": "#/properties/summary/properties/count"
},
"complete": {
"type": [
"boolean",
"null"
]
}
},
"additionalProperties": false,
"description": "Aggregates. `count` = total matching trips across all pages. `distanceSum`/`amountSum` cover only the trips returned so far; `complete` is true when this page holds every match (so the sums are final) and false when you must keep paging and add up the rest yourself."
}
},
"required": [
"items",
"pagination",
"summary"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"annotations": {
"title": "List trips",
"readOnlyHint": true,
"destructiveHint": false,
"openWorldHint": false
},
"execution": {
"taskSupport": "forbidden"
}
}
create_trip — write
Create trip
Create a single trip (mileage record) — ideal for importing past trips from a spreadsheet, calendar or another system. Call once per trip. Example — import one spreadsheet row: { "startAt": "2026-03-04T08:30:00+01:00", "stopAt": "2026-03-04T09:05:00+01:00", "distance": 23400, "startLocationPlaceholder": "Home, Copenhagen", "stopLocationPlaceholder": "Client HQ, Roskilde", "tripType": "business", "vehicleId": "<id from list_vehicles>", "organisationId": "<id from list_organisations>", "comment": "Imported from March spreadsheet" } Notes: - `distance` is an integer in the vehicle's local base unit: meters in km countries (23400 = 23.4 km), miles in mile countries. Check via get_account_context first. - `vehicleId`, `organisationId` and `tripType` are required — look up vehicleId/organisationId with get_account_context, list_vehicles and list_organisations before importing. - The reimbursement amount is calculated automatically from the workplace's rates. - Each of start/stop location is required: pass either the saved-location ID (startLocationId/stopLocationId, see list_locations) or a free-text placeholder (startLocationPlaceholder/stopLocationPlaceholder) — ID preferred when a saved location matches. - Each call costs one request of the 2,000/month quota, so confirm the mapping on 1-2 trips before importing a large batch.
Full tool specification (JSON)
{
"name": "create_trip",
"title": "Create trip",
"description": "Create a single trip (mileage record) — ideal for importing past trips from a spreadsheet, calendar or another system. Call once per trip.\n\nExample — import one spreadsheet row:\n{\n \"startAt\": \"2026-03-04T08:30:00+01:00\",\n \"stopAt\": \"2026-03-04T09:05:00+01:00\",\n \"distance\": 23400,\n \"startLocationPlaceholder\": \"Home, Copenhagen\",\n \"stopLocationPlaceholder\": \"Client HQ, Roskilde\",\n \"tripType\": \"business\",\n \"vehicleId\": \"<id from list_vehicles>\",\n \"organisationId\": \"<id from list_organisations>\",\n \"comment\": \"Imported from March spreadsheet\"\n}\n\nNotes:\n- `distance` is an integer in the vehicle's local base unit: meters in km countries (23400 = 23.4 km), miles in mile countries. Check via get_account_context first.\n- `vehicleId`, `organisationId` and `tripType` are required — look up vehicleId/organisationId with get_account_context, list_vehicles and list_organisations before importing.\n- The reimbursement amount is calculated automatically from the workplace's rates.\n- Each of start/stop location is required: pass either the saved-location ID (startLocationId/stopLocationId, see list_locations) or a free-text placeholder (startLocationPlaceholder/stopLocationPlaceholder) — ID preferred when a saved location matches.\n- Each call costs one request of the 2,000/month quota, so confirm the mapping on 1-2 trips before importing a large batch.",
"inputSchema": {
"type": "object",
"properties": {
"startAt": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2})?([.,]\\d+)?(Z|[+-]\\d{2}:?\\d{2})$",
"description": "Trip start date-time (ISO 8601 with timezone), e.g. 2026-03-04T08:30:00+01:00"
},
"stopAt": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2})?([.,]\\d+)?(Z|[+-]\\d{2}:?\\d{2})$",
"description": "Trip end date-time (ISO 8601 with timezone), e.g. 2026-03-04T09:05:00+01:00"
},
"distance": {
"type": "integer",
"minimum": 0,
"description": "Trip distance as an integer in the vehicle's local base unit (meters in km countries, miles in mile countries)"
},
"tripType": {
"type": "string",
"enum": [
"business",
"private",
"medicalOrMoving",
"charitable"
],
"description": "Trip type: business, private, medicalOrMoving or charitable"
},
"vehicleId": {
"type": "string",
"description": "Vehicle ID (see list_vehicles)"
},
"organisationId": {
"type": "string",
"description": "Workplace/organisation ID (see list_organisations) — required for reimbursement to be calculated"
},
"startLocationId": {
"type": "string",
"description": "ID of a saved location where the trip started (see list_locations)"
},
"stopLocationId": {
"type": "string",
"description": "ID of a saved location where the trip ended (see list_locations)"
},
"startLocationPlaceholder": {
"type": "string",
"description": "Free-text start location shown on the trip when no saved location is used"
},
"stopLocationPlaceholder": {
"type": "string",
"description": "Free-text end location shown on the trip when no saved location is used"
},
"comment": {
"type": "string",
"description": "Note shown on the trip and in reports"
},
"tagIds": {
"type": "array",
"items": {
"type": "string"
},
"description": "Tag IDs to attach to the trip"
},
"markAsReviewed": {
"type": "boolean",
"description": "Set the trip's review status to 'done' (default: leave for review)"
}
},
"required": [
"startAt",
"stopAt",
"distance",
"tripType",
"vehicleId",
"organisationId"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"outputSchema": {
"type": "object",
"properties": {
"trip": {
"type": "object",
"properties": {
"id": {
"type": [
"string",
"null"
]
},
"startAt": {
"$ref": "#/properties/trip/properties/id"
},
"stopAt": {
"$ref": "#/properties/trip/properties/id"
},
"distance": {
"type": [
"number",
"null"
],
"description": "Integer in the vehicle's local base unit: meters in km countries, miles in mile countries"
},
"amount": {
"$ref": "#/properties/trip/properties/distance",
"description": "Reimbursement value in the workplace's currency"
},
"comment": {
"$ref": "#/properties/trip/properties/id"
},
"reviewStatus": {
"$ref": "#/properties/trip/properties/id",
"description": "One of: not_ready, pending, done"
},
"routeOrigin": {
"$ref": "#/properties/trip/properties/id"
},
"startLocationPlaceholder": {
"$ref": "#/properties/trip/properties/id"
},
"stopLocationPlaceholder": {
"$ref": "#/properties/trip/properties/id"
},
"startOdometerReading": {
"anyOf": [
{
"type": [
"string",
"number"
]
},
{
"type": "null"
}
]
},
"stopOdometerReading": {
"$ref": "#/properties/trip/properties/startOdometerReading"
},
"startLocationId": {
"$ref": "#/properties/trip/properties/id"
},
"startLocationName": {
"$ref": "#/properties/trip/properties/id"
},
"startLocationAddress": {
"$ref": "#/properties/trip/properties/id"
},
"stopLocationId": {
"$ref": "#/properties/trip/properties/id"
},
"stopLocationName": {
"$ref": "#/properties/trip/properties/id"
},
"stopLocationAddress": {
"$ref": "#/properties/trip/properties/id"
},
"tripType": {
"$ref": "#/properties/trip/properties/id",
"description": "One of: business, private, medicalOrMoving, charitable"
},
"tripTypeName": {
"$ref": "#/properties/trip/properties/id"
},
"organisationId": {
"$ref": "#/properties/trip/properties/id"
},
"organisationName": {
"$ref": "#/properties/trip/properties/id"
},
"vehicleId": {
"$ref": "#/properties/trip/properties/id"
},
"vehicleName": {
"$ref": "#/properties/trip/properties/id"
},
"tags": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"$ref": "#/properties/trip/properties/id"
},
"name": {
"$ref": "#/properties/trip/properties/id"
}
},
"additionalProperties": false
}
},
{
"type": "null"
}
]
}
},
"additionalProperties": false,
"description": "The created trip"
}
},
"required": [
"trip"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"annotations": {
"title": "Create trip",
"readOnlyHint": false,
"destructiveHint": false,
"idempotentHint": false,
"openWorldHint": false
},
"execution": {
"taskSupport": "forbidden"
}
}
classify_trips — write
Classify / bulk-update trips
Update one or many trips in a single call: classify them as business or personal (set the trip type and workplace/organisation), change vehicle, set a tag or comment, and/or mark them as reviewed. This is the efficient way to classify trips — one request instead of one per trip. Example — classify last week's pending trips as business at a workplace, based on the user's calendar: { "ids": ["<trip ids from list_trips>"], "tripType": "business", "organisationId": "<workplace id from list_organisations>", "markAsReviewed": true } Example — mark trips as personal: { "ids": ["..."], "tripType": "private", "markAsReviewed": true } Notes: - All listed trips receive the SAME values. To give trips different classifications, group them and make one call per group. - Find trip IDs (and their current classification / reviewStatus) with list_trips first. - `markAsReviewed: true` sets reviewStatus to 'done', which removes the trips from the user's 'needs review' list. - Only one tag can be applied per bulk call (`tagId`, requires `tagOrganisationId`); attach multiple tags per trip at creation with create_trip instead.
Full tool specification (JSON)
{
"name": "classify_trips",
"title": "Classify / bulk-update trips",
"description": "Update one or many trips in a single call: classify them as business or personal (set the trip type and workplace/organisation), change vehicle, set a tag or comment, and/or mark them as reviewed. This is the efficient way to classify trips — one request instead of one per trip.\n\nExample — classify last week's pending trips as business at a workplace, based on the user's calendar:\n{\n \"ids\": [\"<trip ids from list_trips>\"],\n \"tripType\": \"business\",\n \"organisationId\": \"<workplace id from list_organisations>\",\n \"markAsReviewed\": true\n}\n\nExample — mark trips as personal:\n{ \"ids\": [\"...\"], \"tripType\": \"private\", \"markAsReviewed\": true }\n\nNotes:\n- All listed trips receive the SAME values. To give trips different classifications, group them and make one call per group.\n- Find trip IDs (and their current classification / reviewStatus) with list_trips first.\n- `markAsReviewed: true` sets reviewStatus to 'done', which removes the trips from the user's 'needs review' list.\n- Only one tag can be applied per bulk call (`tagId`, requires `tagOrganisationId`); attach multiple tags per trip at creation with create_trip instead.",
"inputSchema": {
"type": "object",
"properties": {
"ids": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"description": "IDs of the trips to update (from list_trips)"
},
"tripType": {
"type": "string",
"enum": [
"business",
"private",
"medicalOrMoving",
"charitable"
],
"description": "New trip type: business, private, medicalOrMoving or charitable"
},
"organisationId": {
"type": "string",
"description": "Workplace/organisation ID to assign the trips to (see list_organisations)"
},
"vehicleId": {
"type": "string",
"description": "Vehicle ID to assign (see list_vehicles)"
},
"comment": {
"type": "string",
"description": "Comment to set on all listed trips"
},
"startLocationId": {
"type": "string",
"description": "Saved location ID to set as the start location on all listed trips"
},
"stopLocationId": {
"type": "string",
"description": "Saved location ID to set as the end location on all listed trips"
},
"tagId": {
"type": "string",
"description": "A single tag ID to apply to all listed trips (requires tagOrganisationId)"
},
"tagOrganisationId": {
"type": "string",
"description": "The workplace/organisation the tag belongs to (required together with tagId)"
},
"markAsReviewed": {
"type": "boolean",
"description": "Also mark the trips as reviewed (reviewStatus 'done')"
}
},
"required": [
"ids"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"outputSchema": {
"type": "object",
"properties": {
"updatedCount": {
"type": [
"number",
"null"
],
"description": "How many trips were updated"
},
"trips": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": [
"string",
"null"
]
},
"startAt": {
"$ref": "#/properties/trips/items/properties/id"
},
"stopAt": {
"$ref": "#/properties/trips/items/properties/id"
},
"distance": {
"$ref": "#/properties/updatedCount",
"description": "Integer in the vehicle's local base unit: meters in km countries, miles in mile countries"
},
"amount": {
"$ref": "#/properties/updatedCount",
"description": "Reimbursement value in the workplace's currency"
},
"comment": {
"$ref": "#/properties/trips/items/properties/id"
},
"reviewStatus": {
"$ref": "#/properties/trips/items/properties/id",
"description": "One of: not_ready, pending, done"
},
"routeOrigin": {
"$ref": "#/properties/trips/items/properties/id"
},
"startLocationPlaceholder": {
"$ref": "#/properties/trips/items/properties/id"
},
"stopLocationPlaceholder": {
"$ref": "#/properties/trips/items/properties/id"
},
"startOdometerReading": {
"anyOf": [
{
"type": [
"string",
"number"
]
},
{
"type": "null"
}
]
},
"stopOdometerReading": {
"$ref": "#/properties/trips/items/properties/startOdometerReading"
},
"startLocationId": {
"$ref": "#/properties/trips/items/properties/id"
},
"startLocationName": {
"$ref": "#/properties/trips/items/properties/id"
},
"startLocationAddress": {
"$ref": "#/properties/trips/items/properties/id"
},
"stopLocationId": {
"$ref": "#/properties/trips/items/properties/id"
},
"stopLocationName": {
"$ref": "#/properties/trips/items/properties/id"
},
"stopLocationAddress": {
"$ref": "#/properties/trips/items/properties/id"
},
"tripType": {
"$ref": "#/properties/trips/items/properties/id",
"description": "One of: business, private, medicalOrMoving, charitable"
},
"tripTypeName": {
"$ref": "#/properties/trips/items/properties/id"
},
"organisationId": {
"$ref": "#/properties/trips/items/properties/id"
},
"organisationName": {
"$ref": "#/properties/trips/items/properties/id"
},
"vehicleId": {
"$ref": "#/properties/trips/items/properties/id"
},
"vehicleName": {
"$ref": "#/properties/trips/items/properties/id"
},
"tags": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"$ref": "#/properties/trips/items/properties/id"
},
"name": {
"$ref": "#/properties/trips/items/properties/id"
}
},
"additionalProperties": false
}
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
},
"description": "The updated trips"
}
},
"required": [
"trips"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"annotations": {
"title": "Classify / bulk-update trips",
"readOnlyHint": false,
"destructiveHint": true,
"idempotentHint": true,
"openWorldHint": false
},
"execution": {
"taskSupport": "forbidden"
}
}
list_reports — read
List reports
List the user's own mileage reports (documents that collect trips for a period, used for reimbursement or tax documentation), newest data included: period, total distance and amount, currency, state, workplace, vehicle, and download URLs for PDF/Excel. Use this to answer 'what did my March report total?', to find a report's PDF link, or to check which periods already have a report before creating new ones. Notes: - These are the user's personal reports. For reports submitted by team members to a team the user manages, use list_team_reports instead. - `state` is one of: not_created, created, unsubmitted, pending, approved, rejected, processed (states beyond 'created' reflect team submission). - `totalDistance` is in the report's `distanceUnit`; `totalAmount` is in `currency`. - `pagination.total` is the number of reports across all pages; paginate with `first`/`after` using `pagination.nextCursor`.
Full tool specification (JSON)
{
"name": "list_reports",
"title": "List reports",
"description": "List the user's own mileage reports (documents that collect trips for a period, used for reimbursement or tax documentation), newest data included: period, total distance and amount, currency, state, workplace, vehicle, and download URLs for PDF/Excel.\n\nUse this to answer 'what did my March report total?', to find a report's PDF link, or to check which periods already have a report before creating new ones.\n\nNotes:\n- These are the user's personal reports. For reports submitted by team members to a team the user manages, use list_team_reports instead.\n- `state` is one of: not_created, created, unsubmitted, pending, approved, rejected, processed (states beyond 'created' reflect team submission).\n- `totalDistance` is in the report's `distanceUnit`; `totalAmount` is in `currency`.\n- `pagination.total` is the number of reports across all pages; paginate with `first`/`after` using `pagination.nextCursor`.",
"inputSchema": {
"type": "object",
"properties": {
"first": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"description": "Number of items to return (page size). Defaults to 50."
},
"after": {
"type": "string",
"description": "Opaque pagination cursor. Pass the `pagination.nextCursor` from a previous response to fetch the next page."
}
},
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"outputSchema": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": [
"string",
"null"
]
},
"name": {
"$ref": "#/properties/items/items/properties/id"
},
"title": {
"$ref": "#/properties/items/items/properties/id"
},
"startDate": {
"$ref": "#/properties/items/items/properties/id"
},
"endDate": {
"$ref": "#/properties/items/items/properties/id"
},
"totalDistance": {
"type": [
"number",
"null"
],
"description": "In the report's `distanceUnit`"
},
"totalAmount": {
"$ref": "#/properties/items/items/properties/totalDistance",
"description": "In the report's `currency`"
},
"currency": {
"$ref": "#/properties/items/items/properties/id"
},
"distanceUnit": {
"$ref": "#/properties/items/items/properties/id"
},
"reimbursementMethod": {
"$ref": "#/properties/items/items/properties/id"
},
"state": {
"$ref": "#/properties/items/items/properties/id",
"description": "One of: not_created, created, unsubmitted, pending, approved, rejected, processed"
},
"organisationName": {
"$ref": "#/properties/items/items/properties/id"
},
"vehicleName": {
"$ref": "#/properties/items/items/properties/id"
},
"vehicleLicensePlate": {
"$ref": "#/properties/items/items/properties/id"
},
"pdfUrl": {
"$ref": "#/properties/items/items/properties/id",
"description": "Direct download link for the PDF (no sign-in needed). Null while the PDF is still being generated."
},
"excelUrl": {
"$ref": "#/properties/items/items/properties/id",
"description": "Spreadsheet (XLSX) download link. Must be opened in a browser where the user is signed in to Driversnote."
},
"createdAt": {
"$ref": "#/properties/items/items/properties/id"
}
},
"additionalProperties": false
}
},
"pagination": {
"type": "object",
"properties": {
"total": {
"type": "integer"
},
"returned": {
"type": "integer"
},
"hasMore": {
"type": "boolean"
},
"nextCursor": {
"type": [
"string",
"null"
]
}
},
"required": [
"total",
"returned",
"hasMore",
"nextCursor"
],
"additionalProperties": false,
"description": "Pagination. `total` = matching items across ALL pages (use it to answer 'how many'); `returned` = items in this page; pass `nextCursor` back as the `after` input to fetch the next page (null when `hasMore` is false)."
}
},
"required": [
"items",
"pagination"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"annotations": {
"title": "List reports",
"readOnlyHint": true,
"destructiveHint": false,
"openWorldHint": false
},
"execution": {
"taskSupport": "forbidden"
}
}
preview_report — read
Preview report
Calculate what a mileage report WOULD contain for a period, vehicle and workplace — total distance and reimbursement amount, one summary line per rate/trip type, and data-quality warnings — without creating a report. Nothing is saved, so this is the tool for on-the-fly questions like 'what would I be reimbursed for March?', 'how much business mileage did I do in Q2 at my workplace's rate?' or for checking a period before calling create_report — it avoids cluttering the user's report list with throwaway reports. Example: { "vehicleId": "<id>", "organisationId": "<id>", "startDate": "2026-03-01", "endDate": "2026-03-31" } Get vehicleId/organisationId from get_account_context. Pass the exact same arguments to create_report when the user wants the report saved. Reading the result: - `totals.distance` (in `distanceUnit`: km or mi) and `totals.amount` (in `currency`) are the report's grand totals. - `lines` break the total down. `type` is 'rate' for a reimbursed rate (description = the rate's name, e.g. 'Business, first 20,000 km'), a trip type key such as 'business'/'private' when the workplace does not reimburse, 'none' for trips without a rate, or 'gap' for an odometer gap. `percentage` is the line's share of the distance. - `warnings` flag problems the user should fix before creating the report: odometer inconsistencies/missing readings, trips already included in another report (hasDoubleReportedTrips), archived trips, a provisional (not yet confirmed) rate, or the free-plan monthly trip limit (hasPassedMonthlyLimit — create_report will be refused). - `hasReimbursementMethod` is false when the workplace has no reimbursement method, in which case amounts are 0. - For the individual trips behind these numbers call list_trips with the same startDate/endDate/vehicleId/organisationId. - Costs one request of the 2,000/month quota.
Full tool specification (JSON)
{
"name": "preview_report",
"title": "Preview report",
"description": "Calculate what a mileage report WOULD contain for a period, vehicle and workplace — total distance and reimbursement amount, one summary line per rate/trip type, and data-quality warnings — without creating a report. Nothing is saved, so this is the tool for on-the-fly questions like 'what would I be reimbursed for March?', 'how much business mileage did I do in Q2 at my workplace's rate?' or for checking a period before calling create_report — it avoids cluttering the user's report list with throwaway reports.\n\nExample:\n{ \"vehicleId\": \"<id>\", \"organisationId\": \"<id>\", \"startDate\": \"2026-03-01\", \"endDate\": \"2026-03-31\" }\nGet vehicleId/organisationId from get_account_context. Pass the exact same arguments to create_report when the user wants the report saved.\n\nReading the result:\n- `totals.distance` (in `distanceUnit`: km or mi) and `totals.amount` (in `currency`) are the report's grand totals.\n- `lines` break the total down. `type` is 'rate' for a reimbursed rate (description = the rate's name, e.g. 'Business, first 20,000 km'), a trip type key such as 'business'/'private' when the workplace does not reimburse, 'none' for trips without a rate, or 'gap' for an odometer gap. `percentage` is the line's share of the distance.\n- `warnings` flag problems the user should fix before creating the report: odometer inconsistencies/missing readings, trips already included in another report (hasDoubleReportedTrips), archived trips, a provisional (not yet confirmed) rate, or the free-plan monthly trip limit (hasPassedMonthlyLimit — create_report will be refused).\n- `hasReimbursementMethod` is false when the workplace has no reimbursement method, in which case amounts are 0.\n- For the individual trips behind these numbers call list_trips with the same startDate/endDate/vehicleId/organisationId.\n- Costs one request of the 2,000/month quota.",
"inputSchema": {
"type": "object",
"properties": {
"vehicleId": {
"type": "string",
"description": "Vehicle whose trips the report covers (see get_account_context / list_vehicles)"
},
"organisationId": {
"type": "string",
"description": "Workplace/organisation whose rates and trips the report covers (see get_account_context)"
},
"startDate": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "First day of the report period (inclusive), e.g. 2026-03-01"
},
"endDate": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Last day of the report period (inclusive), e.g. 2026-03-31"
},
"tripType": {
"type": "string",
"enum": [
"business",
"private",
"medicalOrMoving",
"charitable"
],
"description": "Restrict the report to one trip type (business, private, medicalOrMoving or charitable). Omit to include all trip types."
},
"showOdometer": {
"type": "boolean",
"description": "Include odometer readings in the report (default false; needed for some tax authorities)"
},
"tagIds": {
"type": "array",
"items": {
"type": "string"
},
"description": "Only include trips carrying at least one of these tag IDs (see list_trips `tags`). Omit for all trips."
}
},
"required": [
"vehicleId",
"organisationId",
"startDate",
"endDate"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"outputSchema": {
"type": "object",
"properties": {
"startDate": {
"type": [
"string",
"null"
]
},
"endDate": {
"$ref": "#/properties/startDate"
},
"vehicleId": {
"$ref": "#/properties/startDate"
},
"vehicleName": {
"$ref": "#/properties/startDate"
},
"organisationId": {
"$ref": "#/properties/startDate"
},
"organisationName": {
"$ref": "#/properties/startDate"
},
"tripType": {
"$ref": "#/properties/startDate",
"description": "One of: business, private, medicalOrMoving, charitable — or null when all trip types are included"
},
"tripTypeName": {
"$ref": "#/properties/startDate"
},
"reimbursementMethod": {
"$ref": "#/properties/startDate"
},
"hasReimbursementMethod": {
"type": [
"boolean",
"null"
]
},
"showOdometer": {
"$ref": "#/properties/hasReimbursementMethod"
},
"distanceUnit": {
"$ref": "#/properties/startDate",
"description": "'km' or 'mi' — the unit of every distance in this result"
},
"currency": {
"$ref": "#/properties/startDate",
"description": "The currency of every amount in this result"
},
"totals": {
"type": "object",
"properties": {
"distance": {
"type": [
"number",
"null"
],
"description": "Total distance in `distanceUnit`"
},
"amount": {
"$ref": "#/properties/totals/properties/distance",
"description": "Total reimbursement in `currency`"
}
},
"additionalProperties": false
},
"lines": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"$ref": "#/properties/startDate",
"description": "'rate', a trip type key (e.g. 'business', 'private'), 'none' or 'gap'"
},
"description": {
"$ref": "#/properties/startDate",
"description": "Human-readable label, e.g. the rate name"
},
"distance": {
"$ref": "#/properties/totals/properties/distance"
},
"amount": {
"$ref": "#/properties/lines/items/properties/distance"
},
"percentage": {
"$ref": "#/properties/totals/properties/distance",
"description": "Share of the total distance, 0-100"
}
},
"additionalProperties": false
}
},
"warnings": {
"type": "object",
"properties": {
"hasOdometerInconsistencies": {
"$ref": "#/properties/hasReimbursementMethod"
},
"hasOdometerMissing": {
"$ref": "#/properties/hasReimbursementMethod"
},
"hasPassedMonthlyLimit": {
"$ref": "#/properties/hasReimbursementMethod",
"description": "True when the free plan's monthly trip limit blocks creating this report"
},
"hasProvisionalRate": {
"$ref": "#/properties/hasReimbursementMethod"
},
"hasDoubleReportedTrips": {
"$ref": "#/properties/hasReimbursementMethod",
"description": "True when some trips are already in another report"
},
"hasArchivedTrips": {
"$ref": "#/properties/hasReimbursementMethod"
}
},
"additionalProperties": false
}
},
"required": [
"totals",
"lines",
"warnings"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"annotations": {
"title": "Preview report",
"readOnlyHint": true,
"destructiveHint": false,
"openWorldHint": false
},
"execution": {
"taskSupport": "forbidden"
}
}
create_report — write
Create report
Create and save a mileage report for a period, vehicle and workplace. The report collects every matching trip, calculates distance and reimbursement at the workplace's rates, and appears in the user's report list with PDF and spreadsheet downloads. Use it when the user actually wants a report to keep, download or submit to their team — for 'what would it total?' questions use preview_report instead, which saves nothing. Recommended flow: preview_report with the same arguments first → check `warnings` → create_report → (team members) submit_report_to_team. Example: { "vehicleId": "<id>", "organisationId": "<id>", "startDate": "2026-03-01", "endDate": "2026-03-31" } Notes: - vehicleId/organisationId come from get_account_context; the inputs are identical to preview_report. - Check list_reports first if there is a risk the period is already reported: creating a second report over the same trips flags them as double-reported. - The returned `pdfUrl` is often null right after creation because the PDF is generated in the background — fetch it a little later with get_report_download_links. `excelUrl` is available immediately but requires a signed-in browser. - On the free plan the API refuses to create a report once the monthly trip limit is passed (preview_report's `warnings.hasPassedMonthlyLimit`). - Each call creates one report and costs one request of the 2,000/month quota.
Full tool specification (JSON)
{
"name": "create_report",
"title": "Create report",
"description": "Create and save a mileage report for a period, vehicle and workplace. The report collects every matching trip, calculates distance and reimbursement at the workplace's rates, and appears in the user's report list with PDF and spreadsheet downloads. Use it when the user actually wants a report to keep, download or submit to their team — for 'what would it total?' questions use preview_report instead, which saves nothing.\n\nRecommended flow: preview_report with the same arguments first → check `warnings` → create_report → (team members) submit_report_to_team.\n\nExample:\n{ \"vehicleId\": \"<id>\", \"organisationId\": \"<id>\", \"startDate\": \"2026-03-01\", \"endDate\": \"2026-03-31\" }\n\nNotes:\n- vehicleId/organisationId come from get_account_context; the inputs are identical to preview_report.\n- Check list_reports first if there is a risk the period is already reported: creating a second report over the same trips flags them as double-reported.\n- The returned `pdfUrl` is often null right after creation because the PDF is generated in the background — fetch it a little later with get_report_download_links. `excelUrl` is available immediately but requires a signed-in browser.\n- On the free plan the API refuses to create a report once the monthly trip limit is passed (preview_report's `warnings.hasPassedMonthlyLimit`).\n- Each call creates one report and costs one request of the 2,000/month quota.",
"inputSchema": {
"type": "object",
"properties": {
"vehicleId": {
"type": "string",
"description": "Vehicle whose trips the report covers (see get_account_context / list_vehicles)"
},
"organisationId": {
"type": "string",
"description": "Workplace/organisation whose rates and trips the report covers (see get_account_context)"
},
"startDate": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "First day of the report period (inclusive), e.g. 2026-03-01"
},
"endDate": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Last day of the report period (inclusive), e.g. 2026-03-31"
},
"tripType": {
"type": "string",
"enum": [
"business",
"private",
"medicalOrMoving",
"charitable"
],
"description": "Restrict the report to one trip type (business, private, medicalOrMoving or charitable). Omit to include all trip types."
},
"showOdometer": {
"type": "boolean",
"description": "Include odometer readings in the report (default false; needed for some tax authorities)"
},
"tagIds": {
"type": "array",
"items": {
"type": "string"
},
"description": "Only include trips carrying at least one of these tag IDs (see list_trips `tags`). Omit for all trips."
}
},
"required": [
"vehicleId",
"organisationId",
"startDate",
"endDate"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"outputSchema": {
"type": "object",
"properties": {
"report": {
"type": "object",
"properties": {
"id": {
"type": [
"string",
"null"
]
},
"name": {
"$ref": "#/properties/report/properties/id"
},
"title": {
"$ref": "#/properties/report/properties/id"
},
"startDate": {
"$ref": "#/properties/report/properties/id"
},
"endDate": {
"$ref": "#/properties/report/properties/id"
},
"totalDistance": {
"type": [
"number",
"null"
],
"description": "In the report's `distanceUnit`"
},
"totalAmount": {
"$ref": "#/properties/report/properties/totalDistance",
"description": "In the report's `currency`"
},
"currency": {
"$ref": "#/properties/report/properties/id"
},
"distanceUnit": {
"$ref": "#/properties/report/properties/id"
},
"reimbursementMethod": {
"$ref": "#/properties/report/properties/id"
},
"state": {
"$ref": "#/properties/report/properties/id",
"description": "One of: not_created, created, unsubmitted, pending, approved, rejected, processed"
},
"organisationName": {
"$ref": "#/properties/report/properties/id"
},
"vehicleName": {
"$ref": "#/properties/report/properties/id"
},
"vehicleLicensePlate": {
"$ref": "#/properties/report/properties/id"
},
"pdfUrl": {
"$ref": "#/properties/report/properties/id",
"description": "Direct download link for the PDF (no sign-in needed). Null while the PDF is still being generated."
},
"excelUrl": {
"$ref": "#/properties/report/properties/id",
"description": "Spreadsheet (XLSX) download link. Must be opened in a browser where the user is signed in to Driversnote."
},
"createdAt": {
"$ref": "#/properties/report/properties/id"
}
},
"additionalProperties": false,
"description": "The created report"
}
},
"required": [
"report"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"annotations": {
"title": "Create report",
"readOnlyHint": false,
"destructiveHint": false,
"idempotentHint": false,
"openWorldHint": false
},
"execution": {
"taskSupport": "forbidden"
}
}
get_report_download_links — read
Get report download links
Get the PDF and spreadsheet (XLSX) download links for one of the user's mileage reports — either by `reportId`, or by searching the user's reports when the ID is not at hand (by period and/or a text match on the report title, vehicle or workplace). Examples: - Known ID: { "reportId": "<id from list_reports or create_report>" } - 'Send me my March report as PDF': { "startDate": "2026-03-01", "endDate": "2026-03-31" } - 'The Q2 report for the van': { "startDate": "2026-04-01", "endDate": "2026-06-30", "search": "van" } How to use the links: - `report.pdfUrl` is a direct download link that works without signing in — share it as-is. It is null while the PDF is still being generated (typically right after create_report); wait a moment and call again. - `report.excelUrl` (the XLSX spreadsheet, https://www.driversnote.com/reports/<id>.xlsx) only works in a browser where the user is signed in to Driversnote, so tell the user to open it rather than trying to fetch it. Search behaviour: - A report matches when its period overlaps the given startDate–endDate and (if `search` is given) its title, name, vehicle name, license plate or workplace name contains the text (case-insensitive). - Exactly one match → returned as `report`. Several matches → `report` is null and up to 20 `candidates` are returned (each with its own links) so you can pick or ask the user. No match → an error; use list_reports to browse or create_report to make one. - The search scans newest reports first, at most 500 reports (5 requests of the monthly quota). Fetching by ID costs one request. - For a team member's report (as a manager), use list_team_reports — its rows carry `report.pdfUrl`.
Full tool specification (JSON)
{
"name": "get_report_download_links",
"title": "Get report download links",
"description": "Get the PDF and spreadsheet (XLSX) download links for one of the user's mileage reports — either by `reportId`, or by searching the user's reports when the ID is not at hand (by period and/or a text match on the report title, vehicle or workplace).\n\nExamples:\n- Known ID: { \"reportId\": \"<id from list_reports or create_report>\" }\n- 'Send me my March report as PDF': { \"startDate\": \"2026-03-01\", \"endDate\": \"2026-03-31\" }\n- 'The Q2 report for the van': { \"startDate\": \"2026-04-01\", \"endDate\": \"2026-06-30\", \"search\": \"van\" }\n\nHow to use the links:\n- `report.pdfUrl` is a direct download link that works without signing in — share it as-is. It is null while the PDF is still being generated (typically right after create_report); wait a moment and call again.\n- `report.excelUrl` (the XLSX spreadsheet, https://www.driversnote.com/reports/<id>.xlsx) only works in a browser where the user is signed in to Driversnote, so tell the user to open it rather than trying to fetch it.\n\nSearch behaviour:\n- A report matches when its period overlaps the given startDate–endDate and (if `search` is given) its title, name, vehicle name, license plate or workplace name contains the text (case-insensitive).\n- Exactly one match → returned as `report`. Several matches → `report` is null and up to 20 `candidates` are returned (each with its own links) so you can pick or ask the user. No match → an error; use list_reports to browse or create_report to make one.\n- The search scans newest reports first, at most 500 reports (5 requests of the monthly quota). Fetching by ID costs one request.\n- For a team member's report (as a manager), use list_team_reports — its rows carry `report.pdfUrl`.",
"inputSchema": {
"type": "object",
"properties": {
"reportId": {
"type": "string",
"description": "Report ID. When given, the search inputs are ignored."
},
"startDate": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Search: only reports whose period overlaps a range starting on this date, e.g. 2026-03-01"
},
"endDate": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Search: only reports whose period overlaps a range ending on this date"
},
"search": {
"type": "string",
"description": "Search: case-insensitive text matched against report title, name, vehicle name, license plate and workplace name"
}
},
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"outputSchema": {
"type": "object",
"properties": {
"report": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": [
"string",
"null"
]
},
"name": {
"$ref": "#/properties/report/anyOf/0/properties/id"
},
"title": {
"$ref": "#/properties/report/anyOf/0/properties/id"
},
"startDate": {
"$ref": "#/properties/report/anyOf/0/properties/id"
},
"endDate": {
"$ref": "#/properties/report/anyOf/0/properties/id"
},
"totalDistance": {
"type": [
"number",
"null"
],
"description": "In the report's `distanceUnit`"
},
"totalAmount": {
"$ref": "#/properties/report/anyOf/0/properties/totalDistance",
"description": "In the report's `currency`"
},
"currency": {
"$ref": "#/properties/report/anyOf/0/properties/id"
},
"distanceUnit": {
"$ref": "#/properties/report/anyOf/0/properties/id"
},
"reimbursementMethod": {
"$ref": "#/properties/report/anyOf/0/properties/id"
},
"state": {
"$ref": "#/properties/report/anyOf/0/properties/id",
"description": "One of: not_created, created, unsubmitted, pending, approved, rejected, processed"
},
"organisationName": {
"$ref": "#/properties/report/anyOf/0/properties/id"
},
"vehicleName": {
"$ref": "#/properties/report/anyOf/0/properties/id"
},
"vehicleLicensePlate": {
"$ref": "#/properties/report/anyOf/0/properties/id"
},
"pdfUrl": {
"$ref": "#/properties/report/anyOf/0/properties/id",
"description": "Direct download link for the PDF (no sign-in needed). Null while the PDF is still being generated."
},
"excelUrl": {
"$ref": "#/properties/report/anyOf/0/properties/id",
"description": "Spreadsheet (XLSX) download link. Must be opened in a browser where the user is signed in to Driversnote."
},
"createdAt": {
"$ref": "#/properties/report/anyOf/0/properties/id"
}
},
"additionalProperties": false
},
{
"type": "null"
}
],
"description": "The report with its `pdfUrl` and `excelUrl`, or null when several reports matched"
},
"candidates": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"$ref": "#/properties/report/anyOf/0/properties/id"
},
"name": {
"$ref": "#/properties/report/anyOf/0/properties/id"
},
"title": {
"$ref": "#/properties/report/anyOf/0/properties/id"
},
"startDate": {
"$ref": "#/properties/report/anyOf/0/properties/id"
},
"endDate": {
"$ref": "#/properties/report/anyOf/0/properties/id"
},
"totalDistance": {
"$ref": "#/properties/report/anyOf/0/properties/totalDistance"
},
"totalAmount": {
"$ref": "#/properties/report/anyOf/0/properties/totalAmount"
},
"currency": {
"$ref": "#/properties/report/anyOf/0/properties/id"
},
"distanceUnit": {
"$ref": "#/properties/report/anyOf/0/properties/id"
},
"reimbursementMethod": {
"$ref": "#/properties/report/anyOf/0/properties/id"
},
"state": {
"$ref": "#/properties/report/anyOf/0/properties/state"
},
"organisationName": {
"$ref": "#/properties/report/anyOf/0/properties/id"
},
"vehicleName": {
"$ref": "#/properties/report/anyOf/0/properties/id"
},
"vehicleLicensePlate": {
"$ref": "#/properties/report/anyOf/0/properties/id"
},
"pdfUrl": {
"$ref": "#/properties/report/anyOf/0/properties/pdfUrl"
},
"excelUrl": {
"$ref": "#/properties/report/anyOf/0/properties/excelUrl"
},
"createdAt": {
"$ref": "#/properties/report/anyOf/0/properties/id"
}
},
"additionalProperties": false
},
"description": "When the search matched more than one report: the matches (max 20), each with its own links"
},
"searched": {
"$ref": "#/properties/report/anyOf/0/properties/totalDistance",
"description": "Number of reports scanned by the search (0 when fetched by ID)"
}
},
"required": [
"report",
"candidates"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"annotations": {
"title": "Get report download links",
"readOnlyHint": true,
"destructiveHint": false,
"openWorldHint": false
},
"execution": {
"taskSupport": "forbidden"
}
}
submit_report_to_team — write
Submit report to team
Submit one of the user's mileage reports to their team for approval and reimbursement. Only relevant when the user is a MEMBER of a team (see `teams[].currentMemberRole` in get_account_context); the team's managers are notified by email and the report shows up in their approval queue as 'pending'. Example: { "reportId": "<id from create_report or list_reports>", "note": "March mileage, incl. the Aarhus client visits" } Notes: - `teamId` is optional: when the user belongs to exactly one team it is resolved automatically (one extra request); if they belong to several, pass the teamId from get_account_context. - The report must belong to the user (list_reports). Reports in state 'created' or 'unsubmitted' can be submitted; a report that was rejected can be re-submitted after the user fixes it. - `note` is shown to the reviewer alongside the report. `reviewerId` (a team member ID, see list_team_members) requests a specific manager as reviewer; omit to let the team's default routing apply. - Confirm with the user before submitting — this notifies other people and cannot be undone through this API. - The result's `teamReport.state` will be 'pending'.
Full tool specification (JSON)
{
"name": "submit_report_to_team",
"title": "Submit report to team",
"description": "Submit one of the user's mileage reports to their team for approval and reimbursement. Only relevant when the user is a MEMBER of a team (see `teams[].currentMemberRole` in get_account_context); the team's managers are notified by email and the report shows up in their approval queue as 'pending'.\n\nExample: { \"reportId\": \"<id from create_report or list_reports>\", \"note\": \"March mileage, incl. the Aarhus client visits\" }\n\nNotes:\n- `teamId` is optional: when the user belongs to exactly one team it is resolved automatically (one extra request); if they belong to several, pass the teamId from get_account_context.\n- The report must belong to the user (list_reports). Reports in state 'created' or 'unsubmitted' can be submitted; a report that was rejected can be re-submitted after the user fixes it.\n- `note` is shown to the reviewer alongside the report. `reviewerId` (a team member ID, see list_team_members) requests a specific manager as reviewer; omit to let the team's default routing apply.\n- Confirm with the user before submitting — this notifies other people and cannot be undone through this API.\n- The result's `teamReport.state` will be 'pending'.",
"inputSchema": {
"type": "object",
"properties": {
"reportId": {
"type": "string",
"description": "ID of the user's report to submit (see list_reports / create_report)"
},
"teamId": {
"type": "string",
"description": "Team to submit to. Optional when the user belongs to exactly one team (see get_account_context)."
},
"note": {
"type": "string",
"description": "Message to the reviewer, shown with the submission"
},
"reviewerId": {
"type": "string",
"description": "Team member ID of the manager who should review it (see list_team_members). Omit for default routing."
}
},
"required": [
"reportId"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"outputSchema": {
"type": "object",
"properties": {
"teamReport": {
"type": "object",
"properties": {
"id": {
"type": [
"string",
"null"
]
},
"state": {
"$ref": "#/properties/teamReport/properties/id",
"description": "'pending' after a successful submission"
},
"stateLabel": {
"$ref": "#/properties/teamReport/properties/id"
},
"teamId": {
"$ref": "#/properties/teamReport/properties/id"
},
"teamName": {
"$ref": "#/properties/teamReport/properties/id"
},
"memberId": {
"$ref": "#/properties/teamReport/properties/id"
},
"memberName": {
"$ref": "#/properties/teamReport/properties/id"
},
"report": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"$ref": "#/properties/teamReport/properties/id"
},
"title": {
"$ref": "#/properties/teamReport/properties/id"
},
"startDate": {
"$ref": "#/properties/teamReport/properties/id"
},
"endDate": {
"$ref": "#/properties/teamReport/properties/id"
},
"totalDistance": {
"type": [
"number",
"null"
]
},
"totalAmount": {
"$ref": "#/properties/teamReport/properties/report/anyOf/0/properties/totalDistance"
},
"currency": {
"$ref": "#/properties/teamReport/properties/id"
},
"distanceUnit": {
"$ref": "#/properties/teamReport/properties/id"
},
"pdfUrl": {
"$ref": "#/properties/teamReport/properties/id"
}
},
"additionalProperties": false
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
}
},
"required": [
"teamReport"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"annotations": {
"title": "Submit report to team",
"readOnlyHint": false,
"destructiveHint": true,
"idempotentHint": false,
"openWorldHint": false
},
"execution": {
"taskSupport": "forbidden"
}
}
list_team_reports — read
List team reports
List mileage reports submitted to a team the user manages or administers — with submitting member (name/email), approval state, report period, total distance and reimbursement amount. This is the tool for team mileage analysis and approval workflows. Use it to answer 'how much mileage did my team submit in Q1?', 'which reports are still pending approval?', or 'what does the company owe each driver for March?' (group by teamMember, sum report.totalAmount). Notes: - The API key impersonates its owner: team reports are only visible if that user is a manager or admin of the team. A permissions error usually means the key's owner lacks that role. - `teamId` is optional and defaults to the user's first team; find team IDs with get_account_context. - Filter by `state`: unsubmitted, pending, approved, rejected, processed. - `startDate`/`endDate` filter on the report period. - `memberEmail` is only returned to team managers/admins. - Each row flattens the submitting member to `memberId`/`memberName`/`memberEmail` and keeps the report itself under `report`. - `pagination.total` is the number of team reports across all pages; paginate with `first`/`after` using `pagination.nextCursor`.
Full tool specification (JSON)
{
"name": "list_team_reports",
"title": "List team reports",
"description": "List mileage reports submitted to a team the user manages or administers — with submitting member (name/email), approval state, report period, total distance and reimbursement amount. This is the tool for team mileage analysis and approval workflows.\n\nUse it to answer 'how much mileage did my team submit in Q1?', 'which reports are still pending approval?', or 'what does the company owe each driver for March?' (group by teamMember, sum report.totalAmount).\n\nNotes:\n- The API key impersonates its owner: team reports are only visible if that user is a manager or admin of the team. A permissions error usually means the key's owner lacks that role.\n- `teamId` is optional and defaults to the user's first team; find team IDs with get_account_context.\n- Filter by `state`: unsubmitted, pending, approved, rejected, processed.\n- `startDate`/`endDate` filter on the report period.\n- `memberEmail` is only returned to team managers/admins.\n- Each row flattens the submitting member to `memberId`/`memberName`/`memberEmail` and keeps the report itself under `report`.\n- `pagination.total` is the number of team reports across all pages; paginate with `first`/`after` using `pagination.nextCursor`.",
"inputSchema": {
"type": "object",
"properties": {
"teamId": {
"type": "string",
"description": "Team ID (defaults to the user's first team; see get_account_context)"
},
"teamMemberId": {
"type": "string",
"description": "Filter by a specific team member's ID"
},
"reviewerId": {
"type": "string",
"description": "Filter by reviewer team member ID"
},
"state": {
"type": "string",
"enum": [
"unsubmitted",
"pending",
"approved",
"rejected",
"processed"
],
"description": "Filter by team report state"
},
"startDate": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Filter: report period start date on/after"
},
"endDate": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Filter: report period end date on/before"
},
"first": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"description": "Number of items to return (page size). Defaults to 50."
},
"after": {
"type": "string",
"description": "Opaque pagination cursor. Pass the `pagination.nextCursor` from a previous response to fetch the next page."
}
},
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"outputSchema": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": [
"string",
"null"
]
},
"state": {
"$ref": "#/properties/items/items/properties/id",
"description": "One of: unsubmitted, pending, approved, rejected, processed"
},
"stateLabel": {
"$ref": "#/properties/items/items/properties/id"
},
"memberId": {
"$ref": "#/properties/items/items/properties/id"
},
"memberName": {
"$ref": "#/properties/items/items/properties/id"
},
"memberEmail": {
"$ref": "#/properties/items/items/properties/id",
"description": "Only returned to team managers/admins"
},
"report": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"$ref": "#/properties/items/items/properties/id"
},
"title": {
"$ref": "#/properties/items/items/properties/id"
},
"startDate": {
"$ref": "#/properties/items/items/properties/id"
},
"endDate": {
"$ref": "#/properties/items/items/properties/id"
},
"totalDistance": {
"type": [
"number",
"null"
]
},
"totalAmount": {
"$ref": "#/properties/items/items/properties/report/anyOf/0/properties/totalDistance"
},
"currency": {
"$ref": "#/properties/items/items/properties/id"
},
"distanceUnit": {
"$ref": "#/properties/items/items/properties/id"
},
"pdfUrl": {
"$ref": "#/properties/items/items/properties/id"
}
},
"additionalProperties": false
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
}
},
"pagination": {
"type": "object",
"properties": {
"total": {
"type": "integer"
},
"returned": {
"type": "integer"
},
"hasMore": {
"type": "boolean"
},
"nextCursor": {
"type": [
"string",
"null"
]
}
},
"required": [
"total",
"returned",
"hasMore",
"nextCursor"
],
"additionalProperties": false,
"description": "Pagination. `total` = matching items across ALL pages (use it to answer 'how many'); `returned` = items in this page; pass `nextCursor` back as the `after` input to fetch the next page (null when `hasMore` is false)."
}
},
"required": [
"items",
"pagination"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"annotations": {
"title": "List team reports",
"readOnlyHint": true,
"destructiveHint": false,
"openWorldHint": false
},
"execution": {
"taskSupport": "forbidden"
}
}
list_team_members — read
List team members
List the members of a team the user belongs to — name, email, role (member, manager or admin), license status and the date of each member's latest tracked trip. This is the tool for 'who is on my team?', for finding a member's `memberId` to filter list_team_reports / summarize_team_reports, or a manager's ID to use as `reviewerId` in submit_report_to_team. Notes: - `teamId` is optional and defaults to the user's default (first) team; find team IDs with get_account_context. The team itself is returned as `team`. Prefer passing the teamId from get_account_context: the API's fallback 'default team' can differ from the teams listed there. - Filter by `role`: 'member' (drivers who submit reports), 'manager' or 'admin' (who approve them). - Email, license and activity fields (`userEmail`, `userHasLicense`, `userHasTeamLicense`, `userLatestTripCreatedAt`, `userHasPassedMonthlyLimit`) are only returned when the API key's owner is a manager/admin of the team (or for the owner's own row); otherwise they are null. - `userLatestTripCreatedAt` is the best available activity signal: null means the member has never tracked a trip. - For a period-based activity overview (who tracked, who has not submitted a report) use get_team_activity instead. - `pagination.total` is the member count across all pages; paginate with `first`/`after` using `pagination.nextCursor`.
Full tool specification (JSON)
{
"name": "list_team_members",
"title": "List team members",
"description": "List the members of a team the user belongs to — name, email, role (member, manager or admin), license status and the date of each member's latest tracked trip. This is the tool for 'who is on my team?', for finding a member's `memberId` to filter list_team_reports / summarize_team_reports, or a manager's ID to use as `reviewerId` in submit_report_to_team.\n\nNotes:\n- `teamId` is optional and defaults to the user's default (first) team; find team IDs with get_account_context. The team itself is returned as `team`. Prefer passing the teamId from get_account_context: the API's fallback 'default team' can differ from the teams listed there.\n- Filter by `role`: 'member' (drivers who submit reports), 'manager' or 'admin' (who approve them).\n- Email, license and activity fields (`userEmail`, `userHasLicense`, `userHasTeamLicense`, `userLatestTripCreatedAt`, `userHasPassedMonthlyLimit`) are only returned when the API key's owner is a manager/admin of the team (or for the owner's own row); otherwise they are null.\n- `userLatestTripCreatedAt` is the best available activity signal: null means the member has never tracked a trip.\n- For a period-based activity overview (who tracked, who has not submitted a report) use get_team_activity instead.\n- `pagination.total` is the member count across all pages; paginate with `first`/`after` using `pagination.nextCursor`.",
"inputSchema": {
"type": "object",
"properties": {
"teamId": {
"type": "string",
"description": "Team ID (defaults to the user's default team; see get_account_context)"
},
"role": {
"type": "string",
"enum": [
"member",
"manager",
"admin"
],
"description": "Only members with this role"
},
"first": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"description": "Number of items to return (page size). Defaults to 50."
},
"after": {
"type": "string",
"description": "Opaque pagination cursor. Pass the `pagination.nextCursor` from a previous response to fetch the next page."
}
},
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"outputSchema": {
"type": "object",
"properties": {
"team": {
"type": "object",
"properties": {
"id": {
"type": [
"string",
"null"
]
},
"name": {
"$ref": "#/properties/team/properties/id"
}
},
"additionalProperties": false
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"$ref": "#/properties/team/properties/id",
"description": "Team member ID (use as memberId / teamMemberId / reviewerId in other tools)"
},
"userId": {
"$ref": "#/properties/team/properties/id"
},
"userName": {
"$ref": "#/properties/team/properties/id"
},
"userEmail": {
"$ref": "#/properties/team/properties/id",
"description": "Only returned to team managers/admins"
},
"role": {
"$ref": "#/properties/team/properties/id",
"description": "One of: member, manager, admin"
},
"isManagerOrAdmin": {
"type": [
"boolean",
"null"
]
},
"isDeleted": {
"$ref": "#/properties/items/items/properties/isManagerOrAdmin"
},
"userHasLicense": {
"$ref": "#/properties/items/items/properties/isManagerOrAdmin",
"description": "Whether the member has a paid Driversnote subscription (managers/admins only)"
},
"userHasTeamLicense": {
"$ref": "#/properties/items/items/properties/isManagerOrAdmin",
"description": "Whether the member's license is paid for by the team (managers/admins only)"
},
"userHasPassedMonthlyLimit": {
"$ref": "#/properties/items/items/properties/isManagerOrAdmin",
"description": "Free-plan member who hit the monthly trip limit (managers/admins only)"
},
"userLatestTripCreatedAt": {
"$ref": "#/properties/team/properties/id",
"description": "Date of the member's most recent trip; null if they never tracked one (managers/admins only)"
}
},
"additionalProperties": false
}
},
"pagination": {
"type": "object",
"properties": {
"total": {
"type": "integer"
},
"returned": {
"type": "integer"
},
"hasMore": {
"type": "boolean"
},
"nextCursor": {
"type": [
"string",
"null"
]
}
},
"required": [
"total",
"returned",
"hasMore",
"nextCursor"
],
"additionalProperties": false,
"description": "Pagination. `total` = matching items across ALL pages (use it to answer 'how many'); `returned` = items in this page; pass `nextCursor` back as the `after` input to fetch the next page (null when `hasMore` is false)."
}
},
"required": [
"team",
"items",
"pagination"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"annotations": {
"title": "List team members",
"readOnlyHint": true,
"destructiveHint": false,
"openWorldHint": false
},
"execution": {
"taskSupport": "forbidden"
}
}
get_team_activity — read
Get team activity
One-request overview of how a team is doing in a period — for managers/admins. Answers 'how is my team doing this month?', 'who hasn't submitted their mileage report?', 'who has stopped tracking?', 'how much mileage has the team reported for Q1?' — all from a single call. Example: { "startDate": "2026-03-01", "endDate": "2026-03-31" } (teamId optional; defaults to the user's default team, see get_account_context) Prefer passing the teamId from get_account_context: the API's fallback 'default team' can differ from the teams listed there. What comes back: - `members`: counts by role plus `trackingSincePeriodStart` / `notTracking`. The API only exposes each member's latest trip date, so 'tracking' means the member created a trip on or after `startDate` (their latest trip date is not before it); 'not tracking' means their latest trip is older than the period or they never tracked. - `reports`: team reports whose period overlaps the range, counted by state (pending = awaiting approval, approved, processed = paid out, rejected, unsubmitted = withdrawn draft), plus `notSubmitted` = drivers (role 'member') without a submitted report for the period. - `submittedTotals`: distance and amount across pending/approved/processed reports, grouped by currency + distance unit (rejected and unsubmitted reports are excluded). Distance is in `distanceUnit` (km or mi), amount in `currency`. - `missingReports`: the drivers who have not submitted for the period — name and email for follow-up. - `memberActivity`: one row per member with latest trip date, tracking flag, reports submitted in the period, their distance/amount and whether a report is missing. - `complete` is false when the team has more than 100 members or reports in the period; totals then cover only the first 100 — use summarize_team_reports (pages everything) and list_team_members for exact figures. Notes: - Requires the API key's owner to be a manager or admin of the team; members only see their own row. - Managers/admins are not expected to submit reports, so they never appear in `missingReports`. - For the money view alone (per-member payout totals with every report listed) use summarize_team_reports; for the raw report rows use list_team_reports.
Full tool specification (JSON)
{
"name": "get_team_activity",
"title": "Get team activity",
"description": "One-request overview of how a team is doing in a period — for managers/admins. Answers 'how is my team doing this month?', 'who hasn't submitted their mileage report?', 'who has stopped tracking?', 'how much mileage has the team reported for Q1?' — all from a single call.\n\nExample: { \"startDate\": \"2026-03-01\", \"endDate\": \"2026-03-31\" } (teamId optional; defaults to the user's default team, see get_account_context) Prefer passing the teamId from get_account_context: the API's fallback 'default team' can differ from the teams listed there.\n\nWhat comes back:\n- `members`: counts by role plus `trackingSincePeriodStart` / `notTracking`. The API only exposes each member's latest trip date, so 'tracking' means the member created a trip on or after `startDate` (their latest trip date is not before it); 'not tracking' means their latest trip is older than the period or they never tracked.\n- `reports`: team reports whose period overlaps the range, counted by state (pending = awaiting approval, approved, processed = paid out, rejected, unsubmitted = withdrawn draft), plus `notSubmitted` = drivers (role 'member') without a submitted report for the period.\n- `submittedTotals`: distance and amount across pending/approved/processed reports, grouped by currency + distance unit (rejected and unsubmitted reports are excluded). Distance is in `distanceUnit` (km or mi), amount in `currency`.\n- `missingReports`: the drivers who have not submitted for the period — name and email for follow-up.\n- `memberActivity`: one row per member with latest trip date, tracking flag, reports submitted in the period, their distance/amount and whether a report is missing.\n- `complete` is false when the team has more than 100 members or reports in the period; totals then cover only the first 100 — use summarize_team_reports (pages everything) and list_team_members for exact figures.\n\nNotes:\n- Requires the API key's owner to be a manager or admin of the team; members only see their own row.\n- Managers/admins are not expected to submit reports, so they never appear in `missingReports`.\n- For the money view alone (per-member payout totals with every report listed) use summarize_team_reports; for the raw report rows use list_team_reports.",
"inputSchema": {
"type": "object",
"properties": {
"teamId": {
"type": "string",
"description": "Team ID (defaults to the user's default team; see get_account_context)"
},
"startDate": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "First day of the period, e.g. 2026-03-01"
},
"endDate": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Last day of the period, e.g. 2026-03-31"
}
},
"required": [
"startDate",
"endDate"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"outputSchema": {
"type": "object",
"properties": {
"teamId": {
"type": [
"string",
"null"
]
},
"teamName": {
"$ref": "#/properties/teamId"
},
"startDate": {
"$ref": "#/properties/teamId"
},
"endDate": {
"$ref": "#/properties/teamId"
},
"complete": {
"type": [
"boolean",
"null"
],
"description": "False when the team has more than 100 members or reports in the period; figures then cover only the first 100"
},
"members": {
"type": "object",
"properties": {
"total": {
"type": [
"number",
"null"
]
},
"byRole": {
"type": "object",
"properties": {
"member": {
"$ref": "#/properties/members/properties/total"
},
"manager": {
"$ref": "#/properties/members/properties/total"
},
"admin": {
"$ref": "#/properties/members/properties/total"
}
},
"additionalProperties": false
},
"trackingSincePeriodStart": {
"$ref": "#/properties/members/properties/total",
"description": "Members whose latest trip is on/after startDate"
},
"notTracking": {
"$ref": "#/properties/members/properties/total",
"description": "Members whose latest trip is before startDate, or who never tracked"
}
},
"required": [
"byRole"
],
"additionalProperties": false
},
"reports": {
"type": "object",
"properties": {
"total": {
"$ref": "#/properties/members/properties/total",
"description": "Team reports overlapping the period, all states"
},
"byState": {
"type": "object",
"properties": {
"pending": {
"$ref": "#/properties/members/properties/total"
},
"approved": {
"$ref": "#/properties/members/properties/total"
},
"processed": {
"$ref": "#/properties/members/properties/total"
},
"rejected": {
"$ref": "#/properties/members/properties/total"
},
"unsubmitted": {
"$ref": "#/properties/members/properties/total"
}
},
"additionalProperties": false
},
"notSubmitted": {
"$ref": "#/properties/members/properties/total",
"description": "Drivers (role 'member') without a submitted report for the period"
}
},
"required": [
"byState"
],
"additionalProperties": false
},
"submittedTotals": {
"type": "array",
"items": {
"type": "object",
"properties": {
"currency": {
"$ref": "#/properties/teamId"
},
"distanceUnit": {
"$ref": "#/properties/teamId",
"description": "'km' or 'mi'"
},
"reportCount": {
"$ref": "#/properties/members/properties/total"
},
"distance": {
"$ref": "#/properties/members/properties/total"
},
"amount": {
"$ref": "#/properties/members/properties/total"
}
},
"additionalProperties": false
},
"description": "Distance/amount of pending + approved + processed reports, one entry per currency/unit combination"
},
"missingReports": {
"type": "array",
"items": {
"type": "object",
"properties": {
"memberId": {
"$ref": "#/properties/teamId"
},
"memberName": {
"$ref": "#/properties/teamId"
},
"memberEmail": {
"$ref": "#/properties/teamId"
}
},
"additionalProperties": false
}
},
"memberActivity": {
"type": "array",
"items": {
"type": "object",
"properties": {
"memberId": {
"$ref": "#/properties/teamId"
},
"memberName": {
"$ref": "#/properties/teamId"
},
"memberEmail": {
"$ref": "#/properties/teamId"
},
"role": {
"$ref": "#/properties/teamId"
},
"hasLicense": {
"$ref": "#/properties/complete"
},
"latestTripDate": {
"$ref": "#/properties/teamId"
},
"trackingSincePeriodStart": {
"$ref": "#/properties/memberActivity/items/properties/hasLicense"
},
"reportsSubmitted": {
"$ref": "#/properties/members/properties/total",
"description": "Pending + approved + processed reports in the period"
},
"reportStates": {
"type": "array",
"items": {
"$ref": "#/properties/teamId"
},
"description": "States of all this member's reports in the period"
},
"distance": {
"$ref": "#/properties/members/properties/total",
"description": "Submitted distance in the member's distance unit"
},
"amount": {
"$ref": "#/properties/members/properties/total",
"description": "Submitted amount in the member's currency"
},
"currency": {
"$ref": "#/properties/teamId"
},
"distanceUnit": {
"$ref": "#/properties/teamId"
},
"missingReport": {
"$ref": "#/properties/complete",
"description": "True for drivers who have not submitted for the period"
}
},
"required": [
"reportStates"
],
"additionalProperties": false
}
}
},
"required": [
"members",
"reports",
"submittedTotals",
"missingReports",
"memberActivity"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"annotations": {
"title": "Get team activity",
"readOnlyHint": true,
"destructiveHint": false,
"openWorldHint": false
},
"execution": {
"taskSupport": "forbidden"
}
}
summarize_team_reports — read
Summarize team reports
Aggregate a team's mileage reports for a period into totals per member and per state — the payroll/reimbursement view. Answers 'what do we owe each driver for March?', 'how much mileage has the team claimed this quarter?', 'how many reports are still pending, and for what amount?'. Unlike list_team_reports, this pages through EVERY matching report before summing, so the totals are complete (see `complete`). Example — approved but not yet paid out, ready for payroll: { "startDate": "2026-03-01", "endDate": "2026-03-31", "state": "approved" } Reading the result: - `totals`: report count, distance and amount across all matching reports. Distance is in `distanceUnit` (km or mi), amount in `currency`. If the team mixes currencies or units, `currency`/`distanceUnit` are null and `byCurrency` holds one entry per combination — never add those together. - `byState`: count, distance and amount per state (pending = awaiting approval, approved, processed = paid out, rejected, unsubmitted = withdrawn draft). - `byMember`: one row per driver with their report count, distance, amount, a per-state count and the individual reports (id, title, period, state, amount, pdfUrl) so you can list or download them. Sorted by amount, highest first. - Rejected and unsubmitted reports are included in counts but NOT in distance/amount totals, so totals reflect what was actually claimed. Notes: - `teamId` defaults to the user's default team (see get_account_context). Requires the API key's owner to be a manager/admin of the team. Prefer passing the teamId from get_account_context: the API's fallback 'default team' can differ from the teams listed there. - `startDate`/`endDate` match reports whose period overlaps the range; omit both to summarize all of the team's reports. - Costs one request per 100 reports, at most 10. For a period-based engagement overview (who is tracking, who is missing a report) use get_team_activity.
Full tool specification (JSON)
{
"name": "summarize_team_reports",
"title": "Summarize team reports",
"description": "Aggregate a team's mileage reports for a period into totals per member and per state — the payroll/reimbursement view. Answers 'what do we owe each driver for March?', 'how much mileage has the team claimed this quarter?', 'how many reports are still pending, and for what amount?'. Unlike list_team_reports, this pages through EVERY matching report before summing, so the totals are complete (see `complete`).\n\nExample — approved but not yet paid out, ready for payroll: { \"startDate\": \"2026-03-01\", \"endDate\": \"2026-03-31\", \"state\": \"approved\" }\n\nReading the result:\n- `totals`: report count, distance and amount across all matching reports. Distance is in `distanceUnit` (km or mi), amount in `currency`. If the team mixes currencies or units, `currency`/`distanceUnit` are null and `byCurrency` holds one entry per combination — never add those together.\n- `byState`: count, distance and amount per state (pending = awaiting approval, approved, processed = paid out, rejected, unsubmitted = withdrawn draft).\n- `byMember`: one row per driver with their report count, distance, amount, a per-state count and the individual reports (id, title, period, state, amount, pdfUrl) so you can list or download them. Sorted by amount, highest first.\n- Rejected and unsubmitted reports are included in counts but NOT in distance/amount totals, so totals reflect what was actually claimed.\n\nNotes:\n- `teamId` defaults to the user's default team (see get_account_context). Requires the API key's owner to be a manager/admin of the team. Prefer passing the teamId from get_account_context: the API's fallback 'default team' can differ from the teams listed there.\n- `startDate`/`endDate` match reports whose period overlaps the range; omit both to summarize all of the team's reports.\n- Costs one request per 100 reports, at most 10. For a period-based engagement overview (who is tracking, who is missing a report) use get_team_activity.",
"inputSchema": {
"type": "object",
"properties": {
"teamId": {
"type": "string",
"description": "Team ID (defaults to the user's default team; see get_account_context)"
},
"teamMemberId": {
"type": "string",
"description": "Only this member's reports (see list_team_members)"
},
"state": {
"type": "string",
"enum": [
"unsubmitted",
"pending",
"approved",
"rejected",
"processed"
],
"description": "Only reports in this state"
},
"startDate": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Only reports whose period overlaps a range starting here, e.g. 2026-03-01"
},
"endDate": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Only reports whose period overlaps a range ending here, e.g. 2026-03-31"
}
},
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"outputSchema": {
"type": "object",
"properties": {
"teamId": {
"type": [
"string",
"null"
]
},
"startDate": {
"$ref": "#/properties/teamId"
},
"endDate": {
"$ref": "#/properties/teamId"
},
"complete": {
"type": [
"boolean",
"null"
],
"description": "False when more than 1000 reports matched and the totals cover only the first 1000"
},
"requests": {
"type": [
"number",
"null"
],
"description": "API requests spent on this call"
},
"currency": {
"$ref": "#/properties/teamId",
"description": "The single currency of all matching reports, or null when mixed (see byCurrency)"
},
"distanceUnit": {
"$ref": "#/properties/teamId",
"description": "'km' or 'mi' when uniform, or null when mixed (see byCurrency)"
},
"totals": {
"type": "object",
"properties": {
"reportCount": {
"$ref": "#/properties/requests"
},
"distance": {
"$ref": "#/properties/totals/properties/reportCount"
},
"amount": {
"$ref": "#/properties/totals/properties/reportCount"
}
},
"additionalProperties": false
},
"byCurrency": {
"type": "array",
"items": {
"type": "object",
"properties": {
"currency": {
"$ref": "#/properties/teamId"
},
"distanceUnit": {
"$ref": "#/properties/teamId"
},
"reportCount": {
"$ref": "#/properties/totals/properties/reportCount"
},
"distance": {
"$ref": "#/properties/totals/properties/reportCount"
},
"amount": {
"$ref": "#/properties/totals/properties/reportCount"
}
},
"additionalProperties": false
}
},
"byState": {
"type": "object",
"properties": {
"pending": {
"type": "object",
"properties": {
"reportCount": {
"$ref": "#/properties/totals/properties/reportCount"
},
"distance": {
"$ref": "#/properties/totals/properties/reportCount"
},
"amount": {
"$ref": "#/properties/totals/properties/reportCount"
}
},
"additionalProperties": false
},
"approved": {
"type": "object",
"properties": {
"reportCount": {
"$ref": "#/properties/totals/properties/reportCount"
},
"distance": {
"$ref": "#/properties/totals/properties/reportCount"
},
"amount": {
"$ref": "#/properties/totals/properties/reportCount"
}
},
"additionalProperties": false
},
"processed": {
"type": "object",
"properties": {
"reportCount": {
"$ref": "#/properties/totals/properties/reportCount"
},
"distance": {
"$ref": "#/properties/totals/properties/reportCount"
},
"amount": {
"$ref": "#/properties/totals/properties/reportCount"
}
},
"additionalProperties": false
},
"rejected": {
"type": "object",
"properties": {
"reportCount": {
"$ref": "#/properties/totals/properties/reportCount"
},
"distance": {
"$ref": "#/properties/totals/properties/reportCount"
},
"amount": {
"$ref": "#/properties/totals/properties/reportCount"
}
},
"additionalProperties": false
},
"unsubmitted": {
"type": "object",
"properties": {
"reportCount": {
"$ref": "#/properties/totals/properties/reportCount"
},
"distance": {
"$ref": "#/properties/totals/properties/reportCount"
},
"amount": {
"$ref": "#/properties/totals/properties/reportCount"
}
},
"additionalProperties": false
}
},
"required": [
"pending",
"approved",
"processed",
"rejected",
"unsubmitted"
],
"additionalProperties": false
},
"byMember": {
"type": "array",
"items": {
"type": "object",
"properties": {
"memberId": {
"$ref": "#/properties/teamId"
},
"memberName": {
"$ref": "#/properties/teamId"
},
"memberEmail": {
"$ref": "#/properties/teamId",
"description": "Only returned to team managers/admins"
},
"currency": {
"$ref": "#/properties/teamId"
},
"distanceUnit": {
"$ref": "#/properties/teamId"
},
"reportCount": {
"$ref": "#/properties/totals/properties/reportCount"
},
"distance": {
"$ref": "#/properties/totals/properties/reportCount"
},
"amount": {
"$ref": "#/properties/totals/properties/reportCount"
},
"stateCounts": {
"type": "object",
"properties": {
"pending": {
"$ref": "#/properties/totals/properties/reportCount"
},
"approved": {
"$ref": "#/properties/totals/properties/reportCount"
},
"processed": {
"$ref": "#/properties/totals/properties/reportCount"
},
"rejected": {
"$ref": "#/properties/totals/properties/reportCount"
},
"unsubmitted": {
"$ref": "#/properties/totals/properties/reportCount"
}
},
"additionalProperties": false
},
"reports": {
"type": "array",
"items": {
"type": "object",
"properties": {
"teamReportId": {
"$ref": "#/properties/teamId"
},
"reportId": {
"$ref": "#/properties/teamId"
},
"title": {
"$ref": "#/properties/teamId"
},
"startDate": {
"$ref": "#/properties/teamId"
},
"endDate": {
"$ref": "#/properties/teamId"
},
"state": {
"$ref": "#/properties/teamId"
},
"distance": {
"$ref": "#/properties/totals/properties/reportCount"
},
"amount": {
"$ref": "#/properties/totals/properties/reportCount"
},
"pdfUrl": {
"$ref": "#/properties/teamId"
}
},
"additionalProperties": false
}
}
},
"required": [
"stateCounts",
"reports"
],
"additionalProperties": false
}
}
},
"required": [
"totals",
"byCurrency",
"byState",
"byMember"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"annotations": {
"title": "Summarize team reports",
"readOnlyHint": true,
"destructiveHint": false,
"openWorldHint": false
},
"execution": {
"taskSupport": "forbidden"
}
}
list_vehicles — read
List vehicles
List the user's vehicles with name, license plate, vehicle type (e.g. car, motorcycle, bicycle), odometer usage setting, and the vehicle's country (which determines distance unit — km or mi — and currency). Use this to find the `vehicleId` needed by create_trip, classify_trips and list_trips, and to check whether trip distances are in meters (km countries) or miles. Set `isArchived: false` to only see active vehicles (default returns all). Each row flattens the vehicle type and country into `vehicleTypeId`/`vehicleTypeName`, `countryId`/`countryName`, `distanceUnit` and `currency`.
Full tool specification (JSON)
{
"name": "list_vehicles",
"title": "List vehicles",
"description": "List the user's vehicles with name, license plate, vehicle type (e.g. car, motorcycle, bicycle), odometer usage setting, and the vehicle's country (which determines distance unit — km or mi — and currency).\n\nUse this to find the `vehicleId` needed by create_trip, classify_trips and list_trips, and to check whether trip distances are in meters (km countries) or miles.\n\nSet `isArchived: false` to only see active vehicles (default returns all). Each row flattens the vehicle type and country into `vehicleTypeId`/`vehicleTypeName`, `countryId`/`countryName`, `distanceUnit` and `currency`.",
"inputSchema": {
"type": "object",
"properties": {
"isArchived": {
"type": "boolean",
"description": "true = only archived vehicles, false = only active vehicles, omit = all"
},
"first": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"description": "Number of items to return (page size). Defaults to 50."
},
"after": {
"type": "string",
"description": "Opaque pagination cursor. Pass the `pagination.nextCursor` from a previous response to fetch the next page."
}
},
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"outputSchema": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": [
"string",
"null"
]
},
"name": {
"$ref": "#/properties/items/items/properties/id"
},
"licensePlate": {
"$ref": "#/properties/items/items/properties/id"
},
"isArchived": {
"type": [
"boolean",
"null"
]
},
"odometerUsageId": {
"$ref": "#/properties/items/items/properties/id"
},
"odometerUsageName": {
"$ref": "#/properties/items/items/properties/id"
},
"vehicleTypeId": {
"$ref": "#/properties/items/items/properties/id"
},
"vehicleTypeName": {
"$ref": "#/properties/items/items/properties/id"
},
"countryId": {
"$ref": "#/properties/items/items/properties/id"
},
"countryName": {
"$ref": "#/properties/items/items/properties/id"
},
"distanceUnit": {
"$ref": "#/properties/items/items/properties/id",
"description": "'km' or 'mi' — the vehicle's country distance unit"
},
"currency": {
"$ref": "#/properties/items/items/properties/id"
}
},
"additionalProperties": false
}
},
"pagination": {
"type": "object",
"properties": {
"total": {
"type": "integer"
},
"returned": {
"type": "integer"
},
"hasMore": {
"type": "boolean"
},
"nextCursor": {
"type": [
"string",
"null"
]
}
},
"required": [
"total",
"returned",
"hasMore",
"nextCursor"
],
"additionalProperties": false,
"description": "Pagination. `total` = matching items across ALL pages (use it to answer 'how many'); `returned` = items in this page; pass `nextCursor` back as the `after` input to fetch the next page (null when `hasMore` is false)."
}
},
"required": [
"items",
"pagination"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"annotations": {
"title": "List vehicles",
"readOnlyHint": true,
"destructiveHint": false,
"openWorldHint": false
},
"execution": {
"taskSupport": "forbidden"
}
}
list_organisations — read
List organisations
List the user's organisations — what the end user and the Driversnote app call "workplaces". Returns name, address, whether reimbursement is calculated, and the reimbursement method in use. An organisation/workplace is what a business trip is driven FOR — assigning one to a trip is what classifies it as business for that employer/client. Use this to find the `organisationId` needed by create_trip, classify_trips, list_trips and create-report flows. When talking to the end user, call these "workplaces", not "organisations" — that's the term they know. Set `isArchived: false` to only list active organisations (default returns all). Each row flattens the reimbursement method into `reimbursementMethodId`/`reimbursementMethodName`/`reimbursementMethodDescription`.
Full tool specification (JSON)
{
"name": "list_organisations",
"title": "List organisations",
"description": "List the user's organisations — what the end user and the Driversnote app call \"workplaces\". Returns name, address, whether reimbursement is calculated, and the reimbursement method in use.\n\nAn organisation/workplace is what a business trip is driven FOR — assigning one to a trip is what classifies it as business for that employer/client. Use this to find the `organisationId` needed by create_trip, classify_trips, list_trips and create-report flows.\n\nWhen talking to the end user, call these \"workplaces\", not \"organisations\" — that's the term they know.\n\nSet `isArchived: false` to only list active organisations (default returns all). Each row flattens the reimbursement method into `reimbursementMethodId`/`reimbursementMethodName`/`reimbursementMethodDescription`.",
"inputSchema": {
"type": "object",
"properties": {
"isArchived": {
"type": "boolean",
"description": "true = only archived organisations, false = only active organisations, omit = all"
},
"first": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"description": "Number of items to return (page size). Defaults to 50."
},
"after": {
"type": "string",
"description": "Opaque pagination cursor. Pass the `pagination.nextCursor` from a previous response to fetch the next page."
}
},
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"outputSchema": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": [
"string",
"null"
]
},
"name": {
"$ref": "#/properties/items/items/properties/id"
},
"address": {
"$ref": "#/properties/items/items/properties/id"
},
"isArchived": {
"type": [
"boolean",
"null"
]
},
"isCalculatingReimbursement": {
"$ref": "#/properties/items/items/properties/isArchived"
},
"reimbursementMethodValue": {
"$ref": "#/properties/items/items/properties/id",
"description": "Reimbursement rate/value as a string"
},
"reimbursementMethodId": {
"$ref": "#/properties/items/items/properties/id"
},
"reimbursementMethodName": {
"$ref": "#/properties/items/items/properties/id"
},
"reimbursementMethodDescription": {
"$ref": "#/properties/items/items/properties/id"
}
},
"additionalProperties": false
}
},
"pagination": {
"type": "object",
"properties": {
"total": {
"type": "integer"
},
"returned": {
"type": "integer"
},
"hasMore": {
"type": "boolean"
},
"nextCursor": {
"type": [
"string",
"null"
]
}
},
"required": [
"total",
"returned",
"hasMore",
"nextCursor"
],
"additionalProperties": false,
"description": "Pagination. `total` = matching items across ALL pages (use it to answer 'how many'); `returned` = items in this page; pass `nextCursor` back as the `after` input to fetch the next page (null when `hasMore` is false)."
}
},
"required": [
"items",
"pagination"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"annotations": {
"title": "List organisations",
"readOnlyHint": true,
"destructiveHint": false,
"openWorldHint": false
},
"execution": {
"taskSupport": "forbidden"
}
}
list_locations — read
List saved locations
List the user's saved locations (named places like 'Home', 'Office', 'Client HQ' used on trips), with address and coordinates. Use this to find `startLocationId`/`stopLocationId` values for create_trip and classify_trips — linking trips to saved locations is better than free-text placeholders. Filter with `searchPhrase` to match a name or address substring.
Full tool specification (JSON)
{
"name": "list_locations",
"title": "List saved locations",
"description": "List the user's saved locations (named places like 'Home', 'Office', 'Client HQ' used on trips), with address and coordinates.\n\nUse this to find `startLocationId`/`stopLocationId` values for create_trip and classify_trips — linking trips to saved locations is better than free-text placeholders. Filter with `searchPhrase` to match a name or address substring.",
"inputSchema": {
"type": "object",
"properties": {
"searchPhrase": {
"type": "string",
"description": "Only return locations whose name/address contains this phrase"
},
"first": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"description": "Number of items to return (page size). Defaults to 50."
},
"after": {
"type": "string",
"description": "Opaque pagination cursor. Pass the `pagination.nextCursor` from a previous response to fetch the next page."
}
},
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"outputSchema": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": [
"string",
"null"
]
},
"name": {
"$ref": "#/properties/items/items/properties/id"
},
"address": {
"$ref": "#/properties/items/items/properties/id"
},
"formattedAddress": {
"$ref": "#/properties/items/items/properties/id"
},
"postalDistrictString": {
"$ref": "#/properties/items/items/properties/id"
},
"lat": {
"type": [
"number",
"null"
]
},
"lon": {
"$ref": "#/properties/items/items/properties/lat"
},
"parentTeamId": {
"$ref": "#/properties/items/items/properties/id"
}
},
"additionalProperties": false
}
},
"pagination": {
"type": "object",
"properties": {
"total": {
"type": "integer"
},
"returned": {
"type": "integer"
},
"hasMore": {
"type": "boolean"
},
"nextCursor": {
"type": [
"string",
"null"
]
}
},
"required": [
"total",
"returned",
"hasMore",
"nextCursor"
],
"additionalProperties": false,
"description": "Pagination. `total` = matching items across ALL pages (use it to answer 'how many'); `returned` = items in this page; pass `nextCursor` back as the `after` input to fetch the next page (null when `hasMore` is false)."
}
},
"required": [
"items",
"pagination"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
},
"annotations": {
"title": "List saved locations",
"readOnlyHint": true,
"destructiveHint": false,
"openWorldHint": false
},
"execution": {
"taskSupport": "forbidden"
}
}