Cliniko MCP by usefulapi

Hosted MCP server for Cliniko — patients, appointments, availability, and invoices for AI agents.

Should I use this

Quality & Safety

A
Description quality
98%
Schema completeness
83%
Naming quality
80%
Poisoning risk
100%
Permission match
100%
Protocol compliance
100%

Based on automated analysis of tool definitions and protocol compliance.

Context Cost

~3,491Tokens (tool definitions)
~1.7 KBTypical response size
Significant attention impact (2.73% of 128k context)

This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.

Install

One-Click Install

Add this to your `claude_desktop_config.json` file:

{
  "mcpServers": {
    "cliniko": {
      "url": "https://cliniko.usefulapi.io/mcp"
    }
  }
}

Remote endpoints

https://cliniko.usefulapi.io/mcpstreamable-http

What it can do

Tool inventory

Tools (17)

🟢 Read-only🟡 Write🔴 Delete⚪ Unknown
🟢cliniko_get_account

Get the Cliniko account and subscription details for the authenticated API key. A good first call to sanity-check auth, shard, and User-Agent. GET /account.

Input Schema

{
  "type": "object",
  "properties": {},
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢cliniko_list_patients(first_name, last_name, email, page, per_page, ...)

Search/list patients. Name/email filters use Cliniko 'contains' matching (q[]=field:~value). GET /patients.

Input Schema

{
  "type": "object",
  "properties": {
    "first_name": {
      "description": "Filter by first name (contains match).",
      "type": "string"
    },
    "last_name": {
      "description": "Filter by last name (contains match).",
      "type": "string"
    },
    "email": {
      "description": "Filter by email (contains match).",
      "type": "string"
    },
    "page": {
      "description": "Page number (1-based). Default 1.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "per_page": {
      "description": "Results per page (max 100). Default 50.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 100
    },
    "sort": {
      "description": "Field to sort by, e.g. created_at.",
      "type": "string"
    },
    "order": {
      "description": "Sort direction. asc | desc.",
      "type": "string",
      "enum": [
        "asc",
        "desc"
      ]
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢cliniko_get_patient(id)

Fetch a single patient by id. GET /patients/{id}.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        {
          "type": "string",
          "minLength": 1
        }
      ],
      "description": "Patient id."
    }
  },
  "required": [
    "id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢cliniko_list_appointments(patient_id, practitioner_id, business_id, appointment_type_id, starts_from, ...)

List individual appointments, optionally filtered by patient/practitioner/business/type and a starts_at date-time window (starts_from / starts_to, ISO 8601). GET /individual_appointments.

Input Schema

{
  "type": "object",
  "properties": {
    "patient_id": {
      "description": "Filter by patient id (q[]=patient_id:=).",
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        {
          "type": "string",
          "minLength": 1
        }
      ]
    },
    "practitioner_id": {
      "description": "Filter by practitioner id.",
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        {
          "type": "string",
          "minLength": 1
        }
      ]
    },
    "business_id": {
      "description": "Filter by business id.",
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        {
          "type": "string",
          "minLength": 1
        }
      ]
    },
    "appointment_type_id": {
      "description": "Filter by appointment type id.",
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        {
          "type": "string",
          "minLength": 1
        }
      ]
    },
    "starts_from": {
      "description": "Only appointments starting at/after this ISO 8601 time (q[]=starts_at:>).",
      "type": "string"
    },
    "starts_to": {
      "description": "Only appointments starting before this ISO 8601 time (q[]=starts_at:<).",
      "type": "string"
    },
    "page": {
      "description": "Page number (1-based). Default 1.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "per_page": {
      "description": "Results per page (max 100). Default 50.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 100
    },
    "sort": {
      "description": "Field to sort by, e.g. created_at.",
      "type": "string"
    },
    "order": {
      "description": "Sort direction. asc | desc.",
      "type": "string",
      "enum": [
        "asc",
        "desc"
      ]
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢cliniko_get_appointment(id)

Fetch a single individual appointment by id. GET /individual_appointments/{id}.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        {
          "type": "string",
          "minLength": 1
        }
      ],
      "description": "Individual appointment id."
    }
  },
  "required": [
    "id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢cliniko_list_practitioners(page, per_page)

List practitioners in the account. GET /practitioners.

Input Schema

{
  "type": "object",
  "properties": {
    "page": {
      "description": "Page number (1-based). Default 1.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "per_page": {
      "description": "Results per page (max 100). Default 50.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 100
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢cliniko_list_businesses(page, per_page)

List businesses (practice locations) in the account. GET /businesses.

Input Schema

{
  "type": "object",
  "properties": {
    "page": {
      "description": "Page number (1-based). Default 1.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "per_page": {
      "description": "Results per page (max 100). Default 50.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 100
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢cliniko_list_appointment_types(page, per_page)

List appointment types (service definitions). GET /appointment_types.

Input Schema

{
  "type": "object",
  "properties": {
    "page": {
      "description": "Page number (1-based). Default 1.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "per_page": {
      "description": "Results per page (max 100). Default 50.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 100
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢cliniko_list_products(page, per_page)

List billable products/items. GET /products.

Input Schema

{
  "type": "object",
  "properties": {
    "page": {
      "description": "Page number (1-based). Default 1.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "per_page": {
      "description": "Results per page (max 100). Default 50.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 100
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢cliniko_list_invoices(patient_id, page, per_page, sort, order)

List invoices, optionally filtered by patient. GET /invoices.

Input Schema

{
  "type": "object",
  "properties": {
    "patient_id": {
      "description": "Filter by patient id (q[]=patient_id:=).",
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        {
          "type": "string",
          "minLength": 1
        }
      ]
    },
    "page": {
      "description": "Page number (1-based). Default 1.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "per_page": {
      "description": "Results per page (max 100). Default 50.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 100
    },
    "sort": {
      "description": "Field to sort by, e.g. created_at.",
      "type": "string"
    },
    "order": {
      "description": "Sort direction. asc | desc.",
      "type": "string",
      "enum": [
        "asc",
        "desc"
      ]
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢cliniko_get_invoice(id)

Fetch a single invoice by id. GET /invoices/{id}.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        {
          "type": "string",
          "minLength": 1
        }
      ],
      "description": "Invoice id."
    }
  },
  "required": [
    "id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢cliniko_list_treatment_notes(patient_id, page, per_page)

List treatment notes, optionally filtered by patient. NOTE: treatment notes are protected health information (PHI) — handle with care. Read-only. GET /treatment_notes.

Input Schema

{
  "type": "object",
  "properties": {
    "patient_id": {
      "description": "Filter by patient id (q[]=patient_id:=).",
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        {
          "type": "string",
          "minLength": 1
        }
      ]
    },
    "page": {
      "description": "Page number (1-based). Default 1.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "per_page": {
      "description": "Results per page (max 100). Default 50.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 100
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢cliniko_get_treatment_note(id)

Fetch a single treatment note by id. NOTE: treatment notes are protected health information (PHI). Read-only. GET /treatment_notes/{id}.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        {
          "type": "string",
          "minLength": 1
        }
      ],
      "description": "Treatment note id."
    }
  },
  "required": [
    "id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢cliniko_list_available_times(business_id, practitioner_id, appointment_type_id, from, to)

List bookable appointment slots for a business + practitioner + appointment type within a date range (from/to, yyyy-mm-dd, span <= 7 days). High-value booking-slot lookup. GET /businesses/{business_id}/practitioners/{practitioner_id}/appointment_types/{appointment_type_id}/available_times.

Input Schema

{
  "type": "object",
  "properties": {
    "business_id": {
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        {
          "type": "string",
          "minLength": 1
        }
      ],
      "description": "Business id (path)."
    },
    "practitioner_id": {
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        {
          "type": "string",
          "minLength": 1
        }
      ],
      "description": "Practitioner id (path)."
    },
    "appointment_type_id": {
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        {
          "type": "string",
          "minLength": 1
        }
      ],
      "description": "Appointment type id (path)."
    },
    "from": {
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      "description": "Range start yyyy-mm-dd (cannot be more than 7 days before `to`)."
    },
    "to": {
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      "description": "Range end yyyy-mm-dd (cannot be more than 7 days after `from`)."
    }
  },
  "required": [
    "business_id",
    "practitioner_id",
    "appointment_type_id",
    "from",
    "to"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢cliniko_next_available_time(business_id, practitioner_id, appointment_type_id, from)

Get the single next bookable slot for a business + practitioner + appointment type (optionally from a date). GET /businesses/{business_id}/practitioners/{practitioner_id}/appointment_types/{appointment_type_id}/next_available_time.

Input Schema

{
  "type": "object",
  "properties": {
    "business_id": {
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        {
          "type": "string",
          "minLength": 1
        }
      ],
      "description": "Business id (path)."
    },
    "practitioner_id": {
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        {
          "type": "string",
          "minLength": 1
        }
      ],
      "description": "Practitioner id (path)."
    },
    "appointment_type_id": {
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        {
          "type": "string",
          "minLength": 1
        }
      ],
      "description": "Appointment type id (path)."
    },
    "from": {
      "description": "Optional earliest date yyyy-mm-dd to search from.",
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    }
  },
  "required": [
    "business_id",
    "practitioner_id",
    "appointment_type_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴cliniko_create_patient(first_name, last_name, email, date_of_birth, phone_number, ...)

WRITE — creates a REAL new patient record in the live Cliniko practice. Requires first_name + last_name. POST /patients.

Input Schema

{
  "type": "object",
  "properties": {
    "first_name": {
      "type": "string",
      "minLength": 1,
      "description": "Patient first name (required)."
    },
    "last_name": {
      "type": "string",
      "minLength": 1,
      "description": "Patient last name (required)."
    },
    "email": {
      "description": "Email address.",
      "type": "string"
    },
    "date_of_birth": {
      "description": "Date of birth yyyy-mm-dd.",
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "phone_number": {
      "description": "A phone number (stored as a Mobile phone number).",
      "type": "string"
    },
    "address_1": {
      "description": "Street address line 1.",
      "type": "string"
    },
    "city": {
      "description": "City.",
      "type": "string"
    },
    "state": {
      "description": "State / region.",
      "type": "string"
    },
    "post_code": {
      "description": "Post / ZIP code.",
      "type": "string"
    },
    "country_code": {
      "description": "ISO country code, e.g. AU.",
      "type": "string"
    },
    "notes": {
      "description": "Free-text notes.",
      "type": "string"
    }
  },
  "required": [
    "first_name",
    "last_name"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴cliniko_create_appointment(patient_id, practitioner_id, business_id, appointment_type_id, starts_at, ...)

WRITE — books a REAL new individual appointment in the live Cliniko practice. Requires patient_id, practitioner_id, business_id, appointment_type_id, and starts_at (ISO 8601). ends_at defaults from the appointment type if omitted. POST /individual_appointments.

Input Schema

{
  "type": "object",
  "properties": {
    "patient_id": {
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        {
          "type": "string",
          "minLength": 1
        }
      ],
      "description": "Patient id (required)."
    },
    "practitioner_id": {
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        {
          "type": "string",
          "minLength": 1
        }
      ],
      "description": "Practitioner id (required)."
    },
    "business_id": {
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        {
          "type": "string",
          "minLength": 1
        }
      ],
      "description": "Business id (required)."
    },
    "appointment_type_id": {
      "anyOf": [
        {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        {
          "type": "string",
          "minLength": 1
        }
      ],
      "description": "Appointment type id (required)."
    },
    "starts_at": {
      "type": "string",
      "minLength": 1,
      "description": "Start time, ISO 8601 e.g. 2026-07-20T09:00:00Z (required)."
    },
    "ends_at": {
      "description": "End time, ISO 8601. Defaults from the appointment type if omitted.",
      "type": "string"
    },
    "notes": {
      "description": "Appointment notes.",
      "type": "string"
    }
  },
  "required": [
    "patient_id",
    "practitioner_id",
    "business_id",
    "appointment_type_id",
    "starts_at"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}

Community

Rate this Server

Evidence

Recent observations

verifiedversion not recorded17 tools
verifiedversion not recorded17 tools
verifiedversion not recorded17 tools
verifiedversion not recorded17 tools
failed observationversion not recorded—