MCP tools reference

ZenMaid MCP tools

13 tools for ZenMaid on the Cotlet MCP server. Your agent picks them from tools/list.

MCP server
https://cotlet.dev/mcp/v1
Connects with
Your ZenMaid owner or office manager account
Integration page
ZenMaid
ZenMaid Endpoints
Endpoint Access Description
zenmaid_list_appointments read Appointments in a date range with customer, time, cleaners, price and paid flag.
zenmaid_get_appointment read Full appointment: address, service type, frequency, work items, billing, notes and cleaners.
zenmaid_list_contacts read Contacts with email, phone, address and status.
zenmaid_get_contact read One contact with notes, custom fields, and past and upcoming appointments.
zenmaid_list_cleaners read Active cleaners and teams with their IDs.
zenmaid_create_contact write Add a new contact. ZenMaid starts it as a lead.
zenmaid_create_appointment write Schedule a one-time or recurring appointment for a contact.
zenmaid_reschedule_appointment write Move one appointment to a new date or time.
zenmaid_assign_cleaners write Set the cleaners or team on one appointment, replacing the current ones.
zenmaid_add_note write Add a note to an appointment or to a contact.
zenmaid_cancel_appointment write Set an appointment to Cancelled, optionally notifying the client and cleaner.
zenmaid_mark_appointment_paid write Record an offline payment such as cash, Venmo or PayPal. Does not charge a card.
zenmaid_send_message write Send a customer an email, text or both from one of your communication templates.

MCP tool zenmaid_list_appointments

Returns appointments between two dates, in date and time order. An appointment with nobody assigned has an empty cleaners list. Filter by payment status to find unpaid jobs, or search by customer name, cleaner name, street address or a custom field, as ZenMaid's List View does. Cancelled appointments are included only when you ask for them.

Parameters

Parameters: list_appointments
NameTypeDescription
from required date First day of the range.
to required date Last day of the range.
query string Customer name, cleaner name, street address or custom field value.
paid enum all, paid or unpaid. Default: all.
include_cancelled boolean Also return cancelled appointments. Default: false.
limit integer 1 to 100. Default: 50.
cursor string Next page cursor from the previous call.

tools/call

JSON-RPC

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "zenmaid_list_appointments",
    "arguments": {
      "from": "2026-10-01",
      "to": "2026-10-01"
    }
  }
}

Example response

{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "appointments": [
      {
        "appointment_id": "a_993102",
        "contact": "Sample Customer",
        "date": "2026-10-16",
        "start_time": "09:00",
        "end_time": "12:00",
        "cleaners": [],
        "price": "180.00",
        "paid": false
      },
      {
        "appointment_id": "a_993140",
        "contact": "Sample Household",
        "date": "2026-10-16",
        "start_time": "13:00",
        "end_time": "15:00",
        "cleaners": [
          "Cleaner A"
        ],
        "price": "120.00",
        "paid": false
      }
    ],
    "next_cursor": null
  },
  "isError": false
}

MCP tool zenmaid_get_appointment

Returns one appointment with the service address, service type, whether it belongs to a recurring service, work items, billing (price before tax, tip, paid flag) and its appointment and customer notes. Use it before changing or cancelling an appointment.

Parameters

Parameters: get_appointment
NameTypeDescription
appointment_id required string Appointment ID from list_appointments.

tools/call

JSON-RPC

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "zenmaid_get_appointment",
    "arguments": {
      "appointment_id": "appointment_8c41d2"
    }
  }
}

Example response

{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "appointment_id": "a_993102",
    "contact": {
      "contact_id": "c_48213",
      "name": "Sample Customer"
    },
    "address": "12 Sample Street, Springfield",
    "date": "2026-10-16",
    "start_time": "09:00",
    "end_time": "12:00",
    "service_type": "Deep Clean",
    "recurring": false,
    "cleaners": [],
    "work_items": [
      "Kitchen",
      "Bathrooms"
    ],
    "billing": {
      "price": "180.00",
      "tip": "0.00",
      "paid": false
    },
    "notes": [
      {
        "visibility": "public",
        "body": "Gate code is on the contact."
      }
    ]
  },
  "isError": false
}

MCP tool zenmaid_list_contacts

Searches contacts by name, email, phone or address. Status is one of ZenMaid's four: lead, one_time_customer, recurring_customer or former_customer. ZenMaid sets it from the appointments on the calendar, so a new contact stays a lead until someone books them.

Parameters

Parameters: list_contacts
NameTypeDescription
query string Name, email, phone or address to search.
status enum lead, one_time_customer, recurring_customer or former_customer.
limit integer 1 to 100. Default: 50.
cursor string Next page cursor from the previous call.

tools/call

JSON-RPC

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "zenmaid_list_contacts",
    "arguments": {}
  }
}

Example response

{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "contacts": [
      {
        "contact_id": "c_48213",
        "name": "Sample Customer",
        "email": "customer@example.com",
        "phone": "+1 555 0100",
        "address": "12 Sample Street, Springfield",
        "status": "lead"
      }
    ],
    "next_cursor": null
  },
  "isError": false
}

MCP tool zenmaid_get_contact

Returns one contact profile: addresses, customer notes (public and private), contact custom fields, revenue to date, unpaid balance and a list of their appointments, newest first. Private notes are returned only to owner and office manager accounts.

Parameters

Parameters: get_contact
NameTypeDescription
contact_id required string Contact ID from list_contacts.

tools/call

JSON-RPC

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "zenmaid_get_contact",
    "arguments": {
      "contact_id": "contact_8c41d2"
    }
  }
}

Example response

{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "contact_id": "c_48213",
    "name": "Sample Customer",
    "email": "customer@example.com",
    "phone": "+1 555 0100",
    "status": "one_time_customer",
    "revenue_to_date": "180.00",
    "unpaid_balance": "0.00",
    "notes": [
      {
        "visibility": "private",
        "body": "Prefers morning visits."
      }
    ],
    "appointments": [
      {
        "appointment_id": "a_993102",
        "date": "2026-10-16",
        "paid": false
      }
    ]
  },
  "isError": false
}

MCP tool zenmaid_list_cleaners

Returns the cleaners and teams in your account with their IDs, which assign_cleaners and create_appointment need. Inactive staff are left out unless you ask for them.

Parameters

Parameters: list_cleaners
NameTypeDescription
include_inactive boolean Also list inactive staff. Default: false.

tools/call

JSON-RPC

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "zenmaid_list_cleaners",
    "arguments": {}
  }
}

Example response

{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "cleaners": [
      {
        "cleaner_id": "cl_1207",
        "name": "Cleaner A",
        "type": "cleaner",
        "active": true
      },
      {
        "cleaner_id": "cl_1344",
        "name": "Cleaner B",
        "type": "cleaner",
        "active": true
      },
      {
        "cleaner_id": "tm_21",
        "name": "Team One",
        "type": "team",
        "active": true
      }
    ]
  },
  "isError": false
}

MCP tool zenmaid_create_contact

Adds a contact profile. ZenMaid starts a new contact as a Lead until an appointment is booked. It reaches no one and is undone in one call, so it does not ask for your OK.

Parameters

Parameters: create_contact
NameTypeDescription
first_name required string First name.
last_name string Last name.
email string Email address.
phone string Phone number.
address string Service address.
notes string Customer note, public by default.

tools/call

JSON-RPC

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "zenmaid_create_contact",
    "arguments": {
      "first_name": "first name"
    }
  }
}

Example response

{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "contact_id": "c_48290",
    "name": "Sample Lead",
    "email": "lead@example.com",
    "phone": "+1 555 0111",
    "status": "lead"
  },
  "isError": false
}

Create appointment

write Confirm

MCP tool zenmaid_create_appointment

Books an appointment for an existing contact with a start and end time. Leave cleaner_ids empty to keep it unassigned, and price empty to let ZenMaid calculate it if your account is set up for that. A recurring frequency creates a recurring service. The contact becomes a customer once the appointment is on the calendar. By default you confirm each call; you can switch that off for this tool.

Parameters

Parameters: create_appointment
NameTypeDescription
contact_id required string Contact ID from list_contacts.
date required date Day of the appointment.
start_time required string Start time, HH:MM.
end_time required string End time, HH:MM.
service_type string Service type as set up in your account.
frequency string one_time or a recurring frequency from your account. Default: one_time.
cleaner_ids string[] Cleaner or team IDs from list_cleaners. Empty leaves it unassigned.
price string Price before tax. Empty lets ZenMaid calculate it if configured.
notes string Appointment note.

tools/call

JSON-RPC

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "zenmaid_create_appointment",
    "arguments": {
      "contact_id": "c_48213",
      "date": "2026-10-16",
      "start_time": "09:00",
      "end_time": "12:00",
      "service_type": "Deep Clean",
      "frequency": "one_time",
      "cleaner_ids": [
        "cl_1207"
      ]
    }
  }
}

Example response

{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "appointment_id": "a_993102",
    "contact": "Sample Customer",
    "date": "2026-10-16",
    "start_time": "09:00",
    "end_time": "12:00",
    "service_type": "Deep Clean",
    "cleaners": [
      "Cleaner A"
    ],
    "price": "180.00",
    "paid": false
  },
  "isError": false
}

Reschedule appointment

write Confirm

MCP tool zenmaid_reschedule_appointment

Moves one appointment, as the Reschedule window does in ZenMaid. It keeps work items, price and status. The length stays the same unless you pass end_time. One-time appointment notes do not carry over, so add them again with add_note. For a recurring appointment, apply_to chooses this one or all future appointments. By default you confirm each call; you can switch that off for this tool.

Parameters

Parameters: reschedule_appointment
NameTypeDescription
appointment_id required string Appointment ID from list_appointments.
date required date New day.
start_time required string New start time, HH:MM.
end_time string New end time, HH:MM. Default: keeps the length.
recalculate_price boolean Recalculate the amount owed for the new length. Default: false.
apply_to enum this_appointment or all_future, for recurring appointments. Default: this_appointment.

tools/call

JSON-RPC

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "zenmaid_reschedule_appointment",
    "arguments": {
      "appointment_id": "a_993102",
      "date": "2026-10-20",
      "start_time": "09:00",
      "apply_to": "this_appointment"
    }
  }
}

Example response

{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "appointment_id": "a_993102",
    "date": "2026-10-19",
    "start_time": "10:00",
    "end_time": "13:00",
    "price": "180.00",
    "price_recalculated": false
  },
  "isError": false
}

MCP tool zenmaid_assign_cleaners

Replaces the cleaners on one appointment. It does not deactivate a cleaner and does not touch the default cleaner of a recurring service. One more call undoes it, so it does not ask for your OK.

Parameters

Parameters: assign_cleaners
NameTypeDescription
appointment_id required string Appointment ID from list_appointments.
cleaner_ids required string[] Cleaner or team IDs from list_cleaners.

tools/call

JSON-RPC

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "zenmaid_assign_cleaners",
    "arguments": {
      "appointment_id": "a_993102",
      "cleaner_ids": [
        "cl_1344"
      ]
    }
  }
}

Example response

{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "appointment_id": "a_993102",
    "cleaners": [
      "Cleaner B"
    ]
  },
  "isError": false
}

Add note

write

MCP tool zenmaid_add_note

Adds an Appointment Note or a Customer Note, as in ZenMaid. A public note goes on the work orders sent to cleaners; a private note is visible only to owners and office managers. It reaches no one and is undone by editing the note, so it does not ask for your OK.

Parameters

Parameters: add_note
NameTypeDescription
appointment_id string Appointment to note. Give this or contact_id.
contact_id string Contact to note.
body required string Note text.
visibility enum public or private. Default: public.

tools/call

JSON-RPC

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "zenmaid_add_note",
    "arguments": {
      "body": "body"
    }
  }
}

Example response

{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "note_id": "n_5521",
    "appointment_id": "a_993102",
    "visibility": "public",
    "body": "Moved one day because of rain."
  },
  "isError": false
}

Cancel appointment

write Confirm

MCP tool zenmaid_cancel_appointment

Sets the status to Cancelled and keeps the record; it never deletes. notify takes none, client, cleaner or both, the same choices ZenMaid offers when you cancel. A cancelled appointment may be hidden by the calendar filters. By default you confirm each call; you can switch that off for this tool.

Parameters

Parameters: cancel_appointment
NameTypeDescription
appointment_id required string Appointment ID from list_appointments.
notify enum none, client, cleaner or both. Default: none.

tools/call

JSON-RPC

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "zenmaid_cancel_appointment",
    "arguments": {
      "appointment_id": "appointment_8c41d2"
    }
  }
}

Example response

{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "appointment_id": "a_993102",
    "status": "Cancelled",
    "notified": [
      "client",
      "cleaner"
    ]
  },
  "isError": false
}

Mark appointment paid

write Confirm

MCP tool zenmaid_mark_appointment_paid

Marks one appointment as paid, like the Mark as paid button in its Billing section. It never charges the card on file. Appointments paid by card cannot be changed this way. The customer's Revenue To Date and Unpaid Balance update. By default you confirm each call; you can switch that off for this tool.

Parameters

Parameters: mark_appointment_paid
NameTypeDescription
appointment_id required string Appointment ID from list_appointments.

tools/call

JSON-RPC

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "zenmaid_mark_appointment_paid",
    "arguments": {
      "appointment_id": "a_991870"
    }
  }
}

Example response

{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "appointment_id": "a_991870",
    "paid": true,
    "total": "120.00"
  },
  "isError": false
}

Send message

write Confirm

MCP tool zenmaid_send_message

Sends from a template under Type of communication, as the Send Text/Email action does. You can replace the template text with your own. ZenMaid only sends if the contact has an email address or phone number on file, and manual texts count toward your SMS usage. By default you confirm each call; you can switch that off for this tool.

Parameters

Parameters: send_message
NameTypeDescription
appointment_id string Appointment the message is about. Give this or contact_id.
contact_id string Contact to message.
template required string Communication template name.
channels enum email, sms or both. Default: email.
body string Replace the template text with your own.

tools/call

JSON-RPC

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "zenmaid_send_message",
    "arguments": {
      "template": "template"
    }
  }
}

Example response

{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "appointment_id": "a_993102",
    "template": "Appointment Reminder",
    "channels": [
      "email",
      "sms"
    ],
    "sent": true
  },
  "isError": false
}