personio-mcp
by gyopiazza
README.md
# personio-mcp
**The missing Personio MCP**
> **Note:** This is a beta product and is not affiliated with Personio in any way.
MCP server exposing Personio's public APIs as tools:
- **Recruiting** (v2): jobs, job categories, candidates, applications, stage transitions
- **Employees** (v1): list/get/create/update employees, absence balances, attribute catalog,
profile pictures
- **Time tracking** (v2): attendance periods and projects (CRUD)
- **Absences** (v1): time-off types, day-based time-offs, hour-based absence periods
- **Documents** (v1): document categories, document uploads
- **Custom reports** (v1): report metadata, report data, column labels
The v1 attendance/project endpoints are deprecated by Personio (sunset 2027-01-31), so this
server uses their v2 successors (`/v2/attendance-periods`, `/v2/projects`). All other personnel
endpoints follow the official v1 Personnel Data API.
Base URL: `https://api.personio.de`
## Credentials
1. **OAuth2 client** — in Personio: Marketplace > Connected integrations > *Create custom
integration* (requires Core Pro plan). Gives you `client_id` / `client_secret`. Enable the
scopes/API resources you need:
- Recruiting: `personio:recruiting:read` (+ write for some flows)
- Personnel data: employee read/write, absence read/write, attendance read/write,
project read/write, document read/write, custom report read
Note the integration's **company ID** — it is required for all personnel-data endpoints.
2. **Recruiting token** (only needed for `personio_create_application`) — static token under
Settings > Integrations > API Credentials. The company ID is visible at
`https://{YOUR_COMPANY}.personio.de/configuration/api/credentials/management`.
## Environment variables
| Variable | Required | Purpose |
| --- | --- | --- |
| `PERSONIO_CLIENT_ID` | yes | OAuth2 client ID |
| `PERSONIO_CLIENT_SECRET` | yes | OAuth2 client secret |
| `PERSONIO_COMPANY_ID` | recommended | Company ID; sent as `X-Company-ID` on all v1 personnel-data requests |
| `PERSONIO_RECRUITING_TOKEN` | for create_application | Static v1 recruiting API token |
| `PERSONIO_API_BASE_URL` | no | Override base URL (default `https://api.personio.de`) |
## Usage
Requires Node.js 20+. Run directly with npx (no install needed):
```sh
PERSONIO_CLIENT_ID=... PERSONIO_CLIENT_SECRET=... PERSONIO_COMPANY_ID=... npx -y personio-mcp@latest
```
### Client config (e.g. Claude Desktop / opencode)
```json
{
"mcpServers": {
"personio": {
"command": "npx",
"args": ["-y", "personio-mcp@latest"],
"env": {
"PERSONIO_CLIENT_ID": "...",
"PERSONIO_CLIENT_SECRET": "...",
"PERSONIO_COMPANY_ID": "..."
}
}
}
}
```
### ChatGPT desktop app
The new ChatGPT desktop app supports local **STDIO** MCP servers and shares its
MCP configuration with Codex CLI and the IDE extension (stored in
`~/.codex/config.toml`).
**Option A — via `config.toml` (recommended, since it lets you set env vars)**
Add this to `~/.codex/config.toml`:
```toml
[mcp_servers.personio]
command = "npx"
args = ["-y", "personio-mcp@latest"]
[mcp_servers.personio.env]
PERSONIO_CLIENT_ID = "..."
PERSONIO_CLIENT_SECRET = "..."
PERSONIO_COMPANY_ID = "..."
# Only needed for personio_create_application:
# PERSONIO_RECRUITING_TOKEN = "..."
```
Then restart ChatGPT. Type `/mcp` in the composer to verify the server connected.
**Option B — via the UI**
1. Open **Settings**, then select **MCP servers**.
2. Select **Add server**.
3. Enter a name (e.g. `personio`), choose **STDIO**, and set the command to
`npx -y personio-mcp@latest`.
4. Save, then select **Restart**.
Note: if you go through the UI, set the credentials in your shell environment so the server
can read them at startup — or prefer Option A, which keeps credentials scoped to the server entry.
## Tools
Health & recruiting:
- `personio_health_check` — verifies credentials work
- `personio_list_jobs`, `personio_get_job`
- `personio_list_job_categories`, `personio_get_job_category`
- `personio_list_candidates`, `personio_get_candidate`
- `personio_list_applications`, `personio_get_application`, `personio_list_application_stage_transitions`
- `personio_create_application` — submits an application (v1); requires the extra env vars above
Employees:
- `personio_list_employees` — offset-paginated; filter by email / updated_since / attributes[]
- `personio_get_employee`, `personio_create_employee`, `personio_update_employee`
- `personio_get_employee_absence_balance`
- `personio_list_employee_attributes` — attribute catalog incl. custom (dynamic) fields
- `personio_get_profile_picture` — returns image content; optional width
Time tracking:
- `personio_list_attendance_periods` — cursor-paginated; rich filters (person, project, dates, status)
- `personio_get_attendance_period`, `personio_create_attendance_period`,
`personio_update_attendance_period`, `personio_delete_attendance_period`
- `personio_list_projects`, `personio_get_project`, `personio_create_project`,
`personio_update_project`, `personio_delete_project`
Absences:
- `personio_list_time_off_types` — includes unit (day/hour) and approval requirements
- `personio_list_time_offs`, `personio_create_time_off`, `personio_get_time_off`, `personio_delete_time_off` — day-based absences
- `personio_list_absence_periods`, `personio_create_absence_period`, `personio_delete_absence_period` — hour-based absences
Documents:
- `personio_list_document_categories`
- `personio_upload_document` — multipart upload; pass text or base64 content (max 30MB)
Custom reports:
- `personio_list_custom_reports`, `personio_get_custom_report`, `personio_list_report_columns`
Notes from the Personio API:
- v2 endpoints (recruiting, attendance periods, projects) are cursor-paginated;
tools return `pagination.next_cursor`.
- v1 personnel endpoints are offset-paginated; tools return
`pagination.total_elements` / `pagination.next_offset`.
- Employees/applications don't expose custom attributes or tags via v2.
- Employee emails cannot be changed after creation.
- Application creation only works for currently published positions and is rate limited
to ~100 applications/min per IP.
- Document uploads are limited to ~60 requests/min.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues