> ## Documentation Index
> Fetch the complete documentation index at: https://docs.modernloop.io/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP Data Model

> Understand ModernLoop scheduling objects, canonical IDs, discovery flows, and pagination.

Use this page to navigate the objects returned by ModernLoop MCP tools. Start a new session with `get_me`: it identifies the acting user, organization, and scopes available to the connection.

## Object graph

An organization contains jobs, users, interview modules, templates, task queues, schedules, and their related records.

```text theme={"dark"}
Organization
├── Jobs ──┬── Job stages
│          └── Applications ── Candidate
│                            └── Scheduling tasks ── Task queue
│                                                  └── Assignee (user)
├── Schedules ── Interview events ── Application / Candidate / Users
├── Users ── Interview-module memberships ── Interview modules
└── Email and calendar templates
```

* An **application** connects a candidate to a job and has a current job stage.
* A **scheduling task** is created for an application and a job stage. It can be assigned to a user and placed in a task queue.
* A **schedule** is a group of interview events. Events identify their participants and connect back to the relevant application and candidate.
* An **interview module** defines training requirements. Its memberships connect users to that module and record their training progress.
* **Templates** are searchable reference records. No current MCP write or scheduling tool consumes a template directly.

## Canonical ID prefixes

Canonical external IDs are a prefix, an underscore, and a 32-character hexadecimal UUID body. For example, `can_a1b2c3d4e5f64789a1b2c3d4e5f64789` is a candidate ID.

| Object               | Prefix | Example                                |
| -------------------- | ------ | -------------------------------------- |
| Candidate            | `can_` | `can_a1b2c3d4e5f64789a1b2c3d4e5f64789` |
| Application          | `app_` | `app_a1b2c3d4e5f64789a1b2c3d4e5f64789` |
| Job                  | `job_` | `job_a1b2c3d4e5f64789a1b2c3d4e5f64789` |
| Job stage            | `stg_` | `stg_a1b2c3d4e5f64789a1b2c3d4e5f64789` |
| Scheduling task      | `tsk_` | `tsk_a1b2c3d4e5f64789a1b2c3d4e5f64789` |
| Task queue           | `que_` | `que_a1b2c3d4e5f64789a1b2c3d4e5f64789` |
| User                 | `usr_` | `usr_a1b2c3d4e5f64789a1b2c3d4e5f64789` |
| Interview module     | `mod_` | `mod_a1b2c3d4e5f64789a1b2c3d4e5f64789` |
| Interview event      | `int_` | `int_a1b2c3d4e5f64789a1b2c3d4e5f64789` |
| Schedule             | `sch_` | `sch_a1b2c3d4e5f64789a1b2c3d4e5f64789` |
| Template             | `tpl_` | `tpl_a1b2c3d4e5f64789a1b2c3d4e5f64789` |
| Organization         | `org_` | `org_a1b2c3d4e5f64789a1b2c3d4e5f64789` |
| User attribute       | `att_` | `att_a1b2c3d4e5f64789a1b2c3d4e5f64789` |
| User attribute value | `atv_` | `atv_a1b2c3d4e5f64789a1b2c3d4e5f64789` |
| Help article         | `hlp_` | `hlp_a1b2c3d4e5f64789a1b2c3d4e5f64789` |

The API also accepts UUID forms where the tool schema permits them, but use canonical prefixed IDs in conversation and stored references so the object type is clear.

## Recommended discovery sequences

Use list tools to discover an ID, then use the matching get tool before a consequential update.

| Goal                                        | Recommended sequence                                                                                                                                                      |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Orient a new connection                     | `get_me` → `get_organization` when `organization:read` is available                                                                                                       |
| Inspect a candidate's progress              | `list_candidates` → `get_candidate` → `list_applications` → `get_application`                                                                                             |
| Create a scheduling task                    | `list_candidates` → `list_applications` → `get_application` → `list_job_stages` (with `job_id` or `ids`) → `get_job_stage` → user confirmation → `create_scheduling_task` |
| Triage your assigned tasks                  | `get_me` → `list_scheduling_tasks` with `my_tasks: true` → `get_scheduling_task` for detail                                                                               |
| Investigate scheduling                      | `list_applications` → `list_scheduling_tasks` → `get_scheduling_task` → `list_schedules` or `list_interview_events`                                                       |
| Select an assignee                          | `list_users` → `get_user` → `update_scheduling_task` after confirmation                                                                                                   |
| Inspect interview training                  | `list_interview_modules` → `get_interview_module` → `list_interview_module_members` → member stats                                                                        |
| Find a queue's work                         | `list_task_queues` → `get_task_queue` → `list_scheduling_tasks` filtered to that queue                                                                                    |
| Answer a how-to or troubleshooting question | `list_help_articles` with a focused query → `get_help_article` for the best match                                                                                         |

Read the current record before an update. For destructive operations, explicitly confirm the target and impact with the user first.

## Pagination and filters

List tools return a cursor when more results are available. To fetch the next page, pass `pagination.next_cursor` back unchanged and retain the exact same filters and sort context used on the first request. Do not reuse a cursor with a different name, status, date, ID, or other filter; start a new list request instead.

List-tool filters are conjunctive when more than one is supplied: each result must satisfy every provided filter. Start with a narrow, stable query when you expect to paginate.

Omit a filter parameter to skip that filter. Providing an empty array filter (for example `assignee_ids=` or `ids: []`) returns `VALIDATION_FAILED`; supply at least one value or omit the parameter entirely. `list_job_stages` requires at least one of `ids` or `job_id`. `list_scheduling_tasks` accepts `my_tasks: true` as shorthand for tasks assigned to the acting user; it cannot be combined with `assignee_ids`.

When a related object is missing or inaccessible, nested relation fields are returned as `null` rather than placeholder records (for example task application, candidate, job, job stage, or note author; schedule application; user `attribute_name` or `module`).

## Naming conventions in tool inputs

Get tools commonly take a camelCase path-style ID such as `candidateId`, `jobStageId`, or `taskQueueId`. List and write payloads can use snake\_case fields. Use the input schema returned by `tools/list` for the exact field names and required values for your client.

## Further reading

* [MCP Tools](/mcp/tools) — complete tool and scope reference
* [ModernLoop MCP](/mcp/setup) — endpoint and OAuth troubleshooting
