Read tools
Available to any key withread scope (which is all keys).
find_user
Search for users by name or email substring. Case-insensitive.Name or email substring to search for.
Max results (default 20, max 50).
user_view
Example prompt: “Find a user named Sarah.”
Backend: GET /api/v2/users?query=...&limit=...
get_user
Get full details for one user by ID — name, email, role, group memberships, status.Internal user ID (from
find_user or other tool).user_view
Example prompt: “Show me everything about user 42.”
Backend: GET /api/v2/users/:userId
find_course
Search for courses by name. Returns matching courses (id, name, status, annotation).Course name substring.
Max results (default 20, max 50).
course_view
Example prompt: “Find the OSHA refresher course.”
Backend: GET /api/v2/courses?query=...&limit=...
get_course
Full details for one course — name, structure, settings, publish state.Internal course ID (from
find_course).course_view
Example prompt: “Show me the structure of course 17.”
Backend: GET /api/v2/courses/:courseId
list_assignments
List course assignments for one user or one group (exactly one required). No top-level “all assignments” view — too much data; the v2 API scopes by user or group.Filter by one user. Mutually exclusive with
groupId.Filter by one group. Mutually exclusive with
userId.user_assign
Example prompts:
- “What is Jamie working on?” → uses
userId - “What courses is the Engineering group assigned?” → uses
groupId
GET /api/v2/users/:userId/courses/assignments or GET /api/v2/groups/:groupId/courses/assignments
list_my_assignments
Courses assigned to the current user (the key’s owner), with deadlines and completion status. Useful for “what training do I owe?” questions. No parameters. Permission: any role (learner+) Example prompt: “What training do I have due this week?” Backend:GET /api/v2/courses/assigned/me
get_compliance_status
The flagship audit tool. Returns compliance breakdown for one course: who’s assigned, who’s done, who’s overdue, completion percentages. Optionally scoped to one group.Course to check compliance against (e.g. OSHA refresher).
Optional: scope to one group of users.
common_stat
Example prompts:
- “Pull a compliance report for OSHA confined-spaces training across all warehouse staff.”
- “Are we ready for the SOC 2 audit on security training?”
GET /api/v2/courses/:courseId/statistics/users?groupId=...
list_certificates
All certificates earned by one user, with issue dates and (when set) expiry dates. Useful for recertification planning.User whose certificates to list.
user_view
Example prompt: “Show Sarah’s certifications and what’s expiring in the next 90 days.”
Backend: GET /api/v2/users/:userId/certificates
get_statistics
High-level analytics — overall engagement, publishing rate, course-creation activity, insights, tag breakdowns.Which surface to query. One of:
overview, publishing, courseCreation, activity, insights, tags.common_stat
Example prompt: “How are we doing on training engagement this quarter?”
Backend: GET /api/v2/statistics/{scope}
For per-course or per-user numbers prefer get_compliance_status or list_assignments.
get_leaderboard
Top learners by points/completion this period.Top N learners (default 10, max 50).
common_stat
Example prompt: “Who are our top 5 learners this week? I want to send them a thank-you.”
Backend: GET /api/v2/statistics/leaders?limit=...
get_audit_log
Read the platform audit log with optional filters. Use for security investigations, compliance questions, and inspecting actions taken by other MCP agents.Filter by acting user.
ISO date or YYYY-MM-DD — start of window.
ISO date or YYYY-MM-DD — end of window.
Max results (default 50, max 250).
Pagination offset.
audit_view
Example prompt: “Pull all admin actions taken last Tuesday.”
Backend: GET /api/v2/audit?fields[author]=...&fields[createdAt][from]=...&fields[createdAt][to]=...
Write tools
Available when the key haswrite scope AND your license tier is full (Business or Enterprise).
assign_training
Assign one course to one learner. Idempotent — re-assigning the same user is a no-op. For bulk operations usebulk_assign instead.
Course to assign.
Learner to assign to.
Unix timestamp (seconds) when the assignment is due. Omit for no deadline.
Unix timestamp for scheduled future assignment. Omit to assign immediately.
user_assign
Example prompts:
- “Assign the new-hire onboarding to user 42, deadline two weeks from now.”
- “Schedule the Q1 compliance refresher for the new sales rep, starting next Monday.”
POST /api/v2/courses/:courseId/assignments/users
bulk_assign
Assign multiple courses to a whole group at once. Use for onboarding bundles or compliance pushes.Group whose members get the assignments.
One or more courses to assign.
Unix-timestamp deadline applied to ALL assignments.
group_assign
Example prompts:
- “Assign all new-hire training to the Engineering group, due in 30 days.”
- “Roll out the safety refresher to all warehouse staff.”
POST /api/v2/courses/:courseId/assignments with {groups: [groupId]}
assign_chain
Assign an entire course chain (an ordered learning path) to users or groups. The caller must own the chain (per-chain ownership rule).Course-chain ID.
Users to assign the chain to.
Groups to assign the chain to.
Unix-timestamp deadline for the whole chain.
user_assign + chain ownership
Example prompt: “Put the new-hire learning path on Marco’s plate, due 45 days from start date.”
Backend: POST /api/v2/courseChains/:chainId/assign
ban_user
Ban a user (revokes their login + course access, preserves history). Use for offboarding. Target must be below the caller’s role in the hierarchy.User to ban.
user_ban + role hierarchy
Example prompt: “Sarah left the company last Friday — disable her account.”
Backend: POST /api/v2/users/banned
unban_user
Restore a previously banned user’s access. Used for reinstating offboarded learners (rehires, contractors who returned, etc.).User to unban.
user_ban + role hierarchy
Example prompt: “Marco’s back from sabbatical — re-enable his account.”
Backend: DELETE /api/v2/users/banned/:userId
change_user_email
Update a user’s email address (e.g. after a name change or domain migration). Triggers the standard email-change notification.User whose email is changing.
New email address.
user_edit + role hierarchy
Example prompt: “Maria changed her name — update her email to maria.gomez@acme.com.”
Backend: POST /api/v2/users/:userId/email/change
clone_course
Duplicate an existing course (creates an unpublished copy that you can then edit). Useful as the first step when forking a course for a different audience or location.Course to clone.
course_edit
Example prompt: “Clone the Forklift Safety course for the new Phoenix warehouse — I’ll customize it for their layout.”
Backend: POST /api/v2/courses/clone with {courseId} in body
AI course generation
Four tools that let an agent build a complete course from a prompt or from uploaded source materials. Available on Business and Enterprise (mcpAccess: "full" + mcpAiAccess: true). Subject to a separate, stricter quota — 5 calls per key per day, 50 per tenant per day.
The typical workflow:
upload_source_material— once per file. Returns asessionId.create_course_from_files(with the sessionId) orcreate_course_from_prompt(no files). Returns ajobId.get_course_generation_status— poll every 3–5 seconds until status iscompleted, then readresult.courseId.
upload_source_material
Read a local file off the user’s machine and upload it as a course source. Text is extracted and embedded immediately. PDF / DOC / DOCX / PNG / JPG / GIF / WebP, 20 MB max per file.Absolute path to a local file on the user’s machine.
Optional. Reuse the same sessionId across multiple uploads to bundle files into one course-generation context. Omit and the tool generates one.
course_edit + license mcpAiAccess
Example prompt: “Use this OSHA confined-spaces PDF I just shared as the source for a new course.”
Returns: { sessionId, filename, chunkCount, message }
Backend: POST /api/v2/chat/source-materials/upload (multipart) then POST /api/v2/chat/source-materials/process
create_course_from_prompt
Generate a complete course (title, modules, lessons, quiz) from a plain-English description. Returns ajobId — the actual generation runs in the background and takes 10–30 seconds.
Plain-English description of the course. Be specific: include the topic, audience, scope.
Optional. Target number of modules. Default 6.
Optional. ISO 639-1 code (
en, es, fr, …). If omitted, the model uses the language of the prompt.Optional. Override the AI-generated title.
course_edit + license mcpAiAccess
Example prompt: “Build a compliance course on confined-space safety for warehouse staff. 6 lessons + a final quiz.”
Returns: { jobId, status, message } — status is always queued here; poll get_course_generation_status.
Backend: POST /api/v2/ai/courses/generate with { prompt, options }
create_course_from_files
Same ascreate_course_from_prompt but grounded in previously-uploaded source materials. The agent must call upload_source_material at least once in this conversation before calling this tool.
Plain-English direction for the course. The uploaded files are the primary source; the prompt sets tone, audience, scope.
The sessionId returned by
upload_source_material.Optional. Target number of modules.
Optional. ISO 639-1 code.
Optional. Override the title.
course_edit + license mcpAiAccess
Example prompt: “Build a new-hire safety training based on these PDFs. 6 lessons, plain language, 10-question final quiz.”
Backend: POST /api/v2/ai/courses/generate with { prompt, sessionId, options }
get_course_generation_status
Poll a queued generation job. Call every 3–5 seconds untilstatus is completed (success — result.courseId is set) or failed (read error.message).
The
jobId returned by create_course_from_prompt or create_course_from_files.GET /api/v2/ai/courses/generate/:jobId
AI course refinement
Three additional MCP tools that operate on courses you (or the agent) already generated. Same license tier as the generation tools (Business and Enterprise) and they share the same daily quota — 5 calls per key per day, 50 per tenant per day. Each call counts as one. The agent uses these three tools in addition tocreate_course_from_prompt / create_course_from_files to iterate on a course rather than starting fresh. Pick the narrowest tool for the user’s intent: regenerate_question for one bad question, regenerate_lesson to rethink a lesson’s brief, refine_course to add new structure to the whole course.
refine_course
Append new elements to an existing course. Append-only by design — this tool cannot delete or modify anything that already exists, only add. Use when the author says “add a section on X” or “add more practice” or “tack a survey at the end”.The course to extend. Get this from
find_course or get_course.Plain-English description of what to add. Examples: “Add a section on emergency procedures”, “Add two more practice quizzes after lesson 3”, “Add a final survey for course feedback”.
course_edit on the specific course (not just the role alias — the user must actually own / share / administer this course).
Returns: { courseId, elementsAdded, transitionsAdded, message }.
Example prompt: “For course 248, add a section on confined-space rescue procedures after the current safety lesson — 2 lessons + a quiz.”
Backend: POST /api/v2/ai/courses/:courseId/refine with { feedback }
regenerate_question
Replace a single quiz question’s text and options. The new question stays on the same concept as the old one (we’re not drifting to a new subject — just rewriting). Previous content is preserved in your workspace audit log.The question to regenerate. Single-choice questions only.
Optional. What’s wrong with the current question and how to improve it. Examples: “Make it harder”, “The distractors are too obvious”, “Reword for clarity”. Omit for a generic “clearer version”.
course_edit on the parent course.
Returns: { questionId, text, options, message } with the new question content.
Example prompt: “Question #5821 in course 248 has confusing wording — make it clearer.”
Backend: POST /api/v2/ai/questions/:questionId/regenerate with { feedback? }
regenerate_lesson
Regenerate the AI-authored brief that drives the lesson’s content. Safe by construction — this does NOT touch any pages the author has already created; it only updates the brief that the editor uses to bootstrap new content.The lesson to regenerate the brief for.
Optional. What’s wrong with the current brief and how to improve it. Examples: “Add a section on the regulatory context”, “Reduce to 3 key points”, “Target supervisors, not learners”. Omit for a generic clarity pass.
course_edit on the parent course.
Returns: { lessonId, brief } with the new brief content (topic, title, description, keyPoints, targetAudience).
Example prompt: “Lesson 312’s brief is too theoretical — make it practical with concrete examples.”
Backend: POST /api/v2/ai/lessons/:lessonId/regenerate with { feedback? }
Coming soon (not yet shipped)
extend_deadline + send_reminder (preview)
Push an assignment’s deadline back, or nudge overdue learners. Currently not shipped because no corresponding v2 backend endpoint exists.Error handling
Every tool maps backend errors to LLM-readable strings:| Backend status | Error shown to LLM |
|---|---|
403 | ”Permission denied — your user does not have rights for this action.” |
404 | ”Not found — check the ID exists.” |
422 | ”Invalid arguments: “ |
429 | ”Rate limit exceeded. Slow down and retry.” |
| Other | The original error message |
Retry-After header. Network errors, 5xx, and connection resets are propagated as Error: ... for the LLM to surface to you.