---
title: "MCP practice and staff tools — HyperCRM"
description: "The nine MCP tools for the practice profile, its settings, staff members and invitations — including the one that sends a real email to the address given."
canonical: "https://hypercrm.app/docs/mcp/practice"
lang: "en"
updated: "2026-07-26"
---

_MCP reference / Practice_

# Practice and people tools

Nine tools covering the practice profile, its settings, staff members, invitations and bug reports. Creating an invitation sends a real email, so it is marked as reaching outside.

[Start the free trial](/dashboard) · [All 60 tools](/docs/mcp/tools)

## How to read this

Each tool below lists its arguments exactly as the input schema declares them — the type, whether it is required, and the permitted values where the schema fixes them. There are no argument descriptions: the schemas carry types, not prose, and inventing a sentence per argument would be writing fiction about a contract.

`practiceId` is never an argument. It comes from your token, and the write paths strip it if a client sends one anyway.

Every example is a complete `tools/call` request with this tool's required arguments filled in. Errors are returned inside a `200` response with `isError` set — see the [MCP overview](/docs/mcp) for that envelope, and the [full catalogue](/docs/mcp/tools) for every tool at a glance.

The practice profile, its members, and staff invitations.

### get_practice

_Read-only, Any member_

Read the practice profile and settings.

**Example call**

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

**Result**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "structuredContent": {
      "status": 200,
      "ok": true,
      "data": { "...": "the requested records" }
    }
  }
}
```

**Errors**

| Code | Status | When |
| --- | --- | --- |
| `unauthorized` | 401 | The bearer token is missing, invalid or expired. |

### get_me

_Read-only, Any member_

Read the calling user, their practice, their membership role and the practice's vertical pack.

**Example call**

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

**Result**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "structuredContent": {
      "status": 200,
      "ok": true,
      "data": { "...": "the requested records" }
    }
  }
}
```

**Errors**

| Code | Status | When |
| --- | --- | --- |
| `unauthorized` | 401 | The bearer token is missing, invalid or expired. |

### list_practice_members

_Read-only, Any member_

List staff members and their roles.

**Example call**

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

**Result**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "structuredContent": {
      "status": 200,
      "ok": true,
      "data": { "...": "the requested records" }
    }
  }
}
```

**Errors**

| Code | Status | When |
| --- | --- | --- |
| `unauthorized` | 401 | The bearer token is missing, invalid or expired. |

### list_invitations

_Read-only, Owner only_

List pending staff invitations.

**Example call**

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

**Result**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "structuredContent": {
      "status": 200,
      "ok": true,
      "data": { "...": "the requested records" }
    }
  }
}
```

**Errors**

| Code | Status | When |
| --- | --- | --- |
| `forbidden` | 403 | The caller is not an owner of the practice. |
| `unauthorized` | 401 | The bearer token is missing, invalid or expired. |

### update_practice

_Writes, Owner only_

Update the practice. Profile fields and settings fields may be mixed in one call; any unrecognized field is rejected.

**Arguments**

| Tool | Type | Required? |
| --- | --- | --- |
| `name` | `string` | Optional |
| `address` | `string` | Optional |
| `phone` | `string` | Optional |
| `addressStreet` | `string` | Optional |
| `addressCity` | `string` | Optional |
| `addressRegion` | `string` | Optional |
| `addressPostcode` | `string` | Optional |
| `email` | `string` | Optional |
| `website` | `string` | Optional |
| `country` | `string` | Optional |
| `currency` | `string` | Optional |
| `legalName` | `string` | Optional |
| `taxId` | `string` | Optional |
| `taxOffice` | `string` | Optional |
| `packId` | `string` | Optional |
| `workTimeStart` | `string` | Optional |
| `workTimeEnd` | `string` | Optional |
| `openingHours` | `array` | Optional |
| `calendarSlotMinutes` | `integer` | Optional |
| `reminderLeadMinutes` | `integer` | Optional |
| `bookingRequestExpiryWorkingHours` | `number` | Optional |
| `reminderChannels` | `object` | Optional |
| `taxPercentage` | `number` | Optional |
| `includeTaxInInvoices` | `boolean` | Optional |
| `taxExemptionNote` | `string` | Optional |
| `timezone` | `string` | Optional |
| `mfaRequired` | `boolean` | Optional |

**Example call**

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

**Result**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "structuredContent": {
      "status": 200,
      "ok": true,
      "data": { "...": "the written record" }
    }
  }
}
```

**Errors**

| Code | Status | When |
| --- | --- | --- |
| `validation_failed` | 400 | An argument is missing, of the wrong type, or outside its allowed values. |
| `not_found` | 404 | The id does not exist in your practice. A malformed id looks identical. |
| `forbidden` | 403 | The caller is not an owner of the practice. |
| `unauthorized` | 401 | The bearer token is missing, invalid or expired. |

### update_me

_Writes, Any member_

Update your own preferences. Only the UI locale is settable.

**Arguments**

| Tool | Type | Required? |
| --- | --- | --- |
| `locale` | `en` \\| `el` | Required |

**Example call**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "update_me",
    "arguments": {
      "locale": "en"
    }
  }
}
```

**Result**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "structuredContent": {
      "status": 200,
      "ok": true,
      "data": { "...": "the written record" }
    }
  }
}
```

**Errors**

| Code | Status | When |
| --- | --- | --- |
| `validation_failed` | 400 | An argument is missing, of the wrong type, or outside its allowed values. |
| `unauthorized` | 401 | The bearer token is missing, invalid or expired. |

### report_bug

_Writes, Any member_

Report a bug in HyperCRM itself. The report is saved and emailed to the HyperCRM team, with who sent it attached. Up to 5 per user per hour. Leave out patient details.

**Arguments**

| Tool | Type | Required? |
| --- | --- | --- |
| `description` | `string` | Required |
| `expected` | `string` | Optional |
| `pagePath` | `string` | Optional |

**Example call**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "report_bug",
    "arguments": {
      "description": "..."
    }
  }
}
```

**Result**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "structuredContent": {
      "status": 200,
      "ok": true,
      "data": { "...": "the written record" }
    }
  }
}
```

**Errors**

| Code | Status | When |
| --- | --- | --- |
| `validation_failed` | 400 | An argument is missing, of the wrong type, or outside its allowed values. |
| `unauthorized` | 401 | The bearer token is missing, invalid or expired. |

### write_practice_member

_Writes, Owner only_

action=update_role sets a membership to owner or assistant; action=remove takes the member off the practice. Both are rejected if they would leave the practice with zero owners.

**Arguments**

| Tool | Type | Required? |
| --- | --- | --- |
| `action` | `update_role` \\| `remove` | Required |
| `membershipId` | `string` | Required |
| `role` | `owner` \\| `assistant` | Optional |

**Example call**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "write_practice_member",
    "arguments": {
      "action": "update_role",
      "membershipId": "0f1c7a2e-...."
    }
  }
}
```

**Result**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "structuredContent": {
      "status": 200,
      "ok": true,
      "data": { "...": "the written record" }
    }
  }
}
```

**Errors**

| Code | Status | When |
| --- | --- | --- |
| `validation_failed` | 400 | An argument is missing, of the wrong type, or outside its allowed values. |
| `not_found` | 404 | The id does not exist in your practice. A malformed id looks identical. |
| `forbidden` | 403 | The caller is not an owner of the practice. |
| `unauthorized` | 401 | The bearer token is missing, invalid or expired. |

### write_invitation

_Writes, Can delete, Reaches outside, Owner only_

action=create SENDS A REAL EMAIL with a single-use join link that expires in 3 days; action=revoke deletes a pending invitation.

**Arguments**

| Tool | Type | Required? |
| --- | --- | --- |
| `action` | `create` \\| `revoke` | Required |
| `invitationId` | `string` | Optional |
| `email` | `string` | Optional |
| `role` | `owner` \\| `assistant` | Optional |

**Example call**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "write_invitation",
    "arguments": {
      "action": "create"
    }
  }
}
```

**Result**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "structuredContent": {
      "status": 200,
      "ok": true,
      "data": { "...": "the written record" }
    }
  }
}
```

**Errors**

| Code | Status | When |
| --- | --- | --- |
| `validation_failed` | 400 | An argument is missing, of the wrong type, or outside its allowed values. |
| `not_found` | 404 | The id does not exist in your practice. A malformed id looks identical. |
| `forbidden` | 403 | The caller is not an owner of the practice. |
| `unauthorized` | 401 | The bearer token is missing, invalid or expired. |

## Common questions

### How is patient data protected?

Patient records are encrypted in transit and at rest, files are stored privately and served through short-lived signed links, and every change is written to an audit log. Staff accounts sign in with passkeys rather than shared passwords.

### Can I export my data?

Yes. Every list in HyperCRM exports to CSV from the app, and your files can be downloaded at any time. Your practice data belongs to you, and there is no export fee or waiting period — on either plan, during the trial, and after you cancel.

### How much does HyperCRM cost?

HyperCRM is paid software. Every practice starts with a 30-day free trial of the full Complete plan, with no card required. After that, plans start at €19 and €29 a month excluding VAT, banded by how many practitioners you have. Every price is printed on the pricing page rather than quoted on a call.