---
title: "Users"
description: "Manage local user accounts in MCPHub."
---

These endpoints manage the local username/password users stored in `mcp_settings.json` (or the `mcphub_user` table when the database backend is enabled). All endpoints require an authenticated admin (`isAdmin: true`).

For OAuth/social accounts created via Better Auth, see `/api/better-auth/*` instead — those records live in a separate table and are not managed through this API.

<Card title="GET /api/users" href="#get-all-users">List all users.</Card>
<Card title="GET /api/users/:username" href="#get-a-user">Get a single user.</Card>
<Card title="POST /api/users" href="#create-a-user">Create a user.</Card>
<Card title="PUT /api/users/:username" href="#update-a-user">Update a user.</Card>
<Card title="DELETE /api/users/:username" href="#delete-a-user">Delete a user.</Card>
<Card title="GET /api/users-stats" href="#get-user-statistics">Aggregate user counts.</Card>

---

### Get All Users

- **Endpoint**: `GET /api/users`
- **Authentication**: Required (admin only)
- **Response**: The `password` field is stripped from every record.

```json
{
  "success": true,
  "data": [
    { "username": "admin", "isAdmin": true },
    { "username": "alice", "isAdmin": false }
  ]
}
```

---

### Get a User

- **Endpoint**: `GET /api/users/:username`
- **Authentication**: Required (admin only)
- **Response**:

```json
{
  "success": true,
  "data": { "username": "alice", "isAdmin": false }
}
```

Returns `404` if the user does not exist.

---

### Create a User

- **Endpoint**: `POST /api/users`
- **Authentication**: Required (admin only)
- **Body**:

```json
{
  "username": "alice",
  "password": "P@ssw0rd-123",
  "isAdmin": false
}
```

| Field | Type | Required | Description |
| ----- | ---- | -------- | ----------- |
| `username` | string | yes | Must be unique. |
| `password` | string | yes | Must satisfy the configured password policy (see `src/utils/passwordValidation.ts`). |
| `isAdmin` | boolean | no | Defaults to `false`. |

- Returns `400` if `username`/`password` are missing, the password is too weak, or the username is already taken.
- Returns `201` with the new user (password stripped) on success.

<Note>
  The user model does not have per-user `servers` or `groups` lists. Server visibility is governed by the `owner` field on each server and by the group membership recorded on the group itself. See [Group Management](/features/group-management) and [MCP Settings](/configuration/mcp-settings).
</Note>

---

### Update a User

- **Endpoint**: `PUT /api/users/:username`
- **Authentication**: Required (admin only)
- **Body** (at least one field is required):

```json
{
  "isAdmin": true,
  "newPassword": "Newp@ssw0rd"
}
```

| Field | Type | Description |
| ----- | ---- | ----------- |
| `isAdmin` | boolean | Promote/demote the user. |
| `newPassword` | string | Replace the user's password. Must satisfy the password policy. |

- Returns `400` if neither field is supplied, the password fails validation, or the request would demote the last remaining admin.
- Returns `404` if the username does not exist.

<Warning>
  Username is the primary key — to rename a user, delete and recreate them. Other profile fields (email, display name, etc.) are not currently supported on the local user model.
</Warning>

---

### Delete a User

- **Endpoint**: `DELETE /api/users/:username`
- **Authentication**: Required (admin only)
- **Restrictions**:
  - You cannot delete your own account.
  - You cannot delete the last admin.

```json
{
  "success": true,
  "message": "User deleted successfully"
}
```

---

### Get User Statistics

- **Endpoint**: `GET /api/users-stats`
- **Authentication**: Required (admin only)

```json
{
  "success": true,
  "data": {
    "totalUsers": 5,
    "adminUsers": 1,
    "regularUsers": 4
  }
}
```

The stats endpoint reports only aggregate counts; per-server or per-group breakdowns are not produced here.
