Consumer and reviewer reference for LW LMS 2.0.1 Abilities API registrations. Use when calling or auditing `lw-lms/list-courses`, `lw-lms/get-course`, `lw-lms/get-progress`, `lw-lms/set-progress`, `lw-lms/get-options`, `/wp-json/wp-abilities/v1/abilities/lw-lms/.../run`, Site Manager bridge integration, MCP discovery, standalone WordPress Abilities API fallback, schemas, permissions, or agent access to course and progress data.
Installs into .claude/skills of the current project.
Are you the author of Lw Lms Abilities?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/lonsdale201-lw-lms-abilities)
---
name: lw-lms-abilities
description: Consumer and reviewer reference for LW LMS 2.0.1 Abilities API registrations. Use when calling or auditing `lw-lms/list-courses`, `lw-lms/get-course`, `lw-lms/get-progress`, `lw-lms/set-progress`, `lw-lms/get-options`, `/wp-json/wp-abilities/v1/abilities/lw-lms/.../run`, Site Manager bridge integration, MCP discovery, standalone WordPress Abilities API fallback, schemas, permissions, or agent access to course and progress data.
metadata:
wp-skills-author: "Soczó Kristóf"
wp-skills-contact: "https://github.com/Lonsdale201"
wp-skills-plugin: "lw-lms"
wp-skills-plugin-version-tested: "2.0.1"
wp-skills-wp-version-tested: "7.1.2"
wp-skills-php-min: "8.0"
wp-skills-last-updated: "2026-09-26"
---
# LW LMS Abilities API
Use this when an AI agent, MCP client, REST consumer, or reviewer works with the machine-callable `lw-lms/*` abilities. This is not the learner-facing `/wp-json/lms/v1` REST API and not the companion-plugin extension hook map; it is the admin/agent-facing ability surface.
## When to use this skill
Trigger this skill when ANY of the following is true:
- The request mentions `lw-lms/list-courses`, `lw-lms/get-course`, `lw-lms/get-progress`, `lw-lms/set-progress`, or `lw-lms/get-options`.
- Code calls `/wp-json/wp-abilities/v1/abilities/lw-lms/.../run`.
- A user asks how an automation agent or MCP client can inspect or mutate LMS course/progress data.
- A diff touches `includes/SiteManager/Integration.php`, `includes/SiteManager/Abilities/`, `OutputSchemas`, or the ability service classes.
- You need to decide whether to call Abilities API vs `/wp-json/lms/v1`.
## Verified registration model
LW LMS 2.0.1 registers the same five abilities in two modes. The quiz, drip, React admin, and privacy releases did not add abilities. They did tighten progress authorization and validation. Version 2.0.1 adds explicit MCP-public metadata so Site Manager can discover the foreign `lw-lms/*` namespace.
1. Site Manager bridge: hooks `lw_site_manager_register_categories` and `lw_site_manager_register_abilities`, receives the Site Manager `PermissionManager`, and registers into category `lms`.
2. Standalone fallback: hooks `wp_abilities_api_categories_init` and `wp_abilities_api_init` at priority 20. `did_action()` guards prevent duplicate registration when Site Manager is active.
Do not claim Site Manager is required for LMS abilities. Since v1.2.16, WordPress 6.9+ Abilities API or the feature plugin is enough.
### MCP visibility
Each ability now carries:
```php
'mcp' => [
'public' => true,
'type' => 'tool',
],
```
With LW Site Manager 1.5.1, all five `lw-lms/*` abilities appear in its discovery response. MCP visibility does not bypass the ability permission callback or the target-object checks.
## Ability catalog
| Ability | Type | Permission key | Input | Output |
|---|---|---|---|---|
| `lw-lms/list-courses` | readonly | `can_edit_posts` | `per_page`, `page` | `success`, `courses`, `total`, `total_pages`, `page`, `per_page` |
| `lw-lms/get-course` | readonly | `can_edit_posts` | required `course_id` | `success`, `course` with sections and lessons |
| `lw-lms/get-progress` | readonly | `can_manage_lms` | required `user_id`, `course_id` | summary plus lesson status map |
| `lw-lms/set-progress` | write | `can_manage_lms` | required `user_id`, `course_id`, `lesson_id`, `status` | `success`, `message` |
| `lw-lms/get-options` | readonly | `can_manage_options` | empty object | `success`, `options` |
`set-progress` accepts only `completed`, `in_progress`, or `not_started`. Reverting from `completed` is a write that loses the completion timestamp for that row; do not treat it as harmless even though `AbilityMeta::write()` marks writes idempotent.
## Calling pattern
Abilities use the core Abilities API route, not the LMS REST namespace:
```bash
curl -X POST "${SITE_URL}/wp-json/wp-abilities/v1/abilities/lw-lms/get-progress/run" \
-u 'admin:xxxx xxxx xxxx xxxx' \
-H 'Content-Type: application/json' \
-d '{"input":{"user_id":7,"course_id":42}}'
```
The request body must wrap arguments in `input`. Direct PHP is also valid:
```php
$ability = wp_get_ability( 'lw-lms/set-progress' );
$result = $ability->execute(
[
'user_id' => 7,
'course_id' => 42,
'lesson_id' => 55,
'status' => 'completed',
]
);
```
## Critical rules
- Use Abilities API for admin/agent operations; use `/wp-json/lms/v1` for learner-facing frontend data.
- Feature-detect with `function_exists( 'wp_register_ability' )` or `wp_get_ability( 'lw-lms/list-courses' )`; the plugin silently skips abilities when the API is unavailable.
- Course abilities continue to use `can_edit_posts`; options use `can_manage_options`. Progress abilities use the LMS-specific `can_manage_lms`, resolved directly as `manage_lms || manage_options` even when Site Manager is present.
- `lw-lms/get-course` returns admin/agent data, not access-gated learner content. Do not expose it directly to public learners.
- `get-progress` rejects missing users and non-course posts. `set-progress` also verifies that the lesson exists and belongs to the supplied course.
- `lw-lms/set-progress` calls `ProgressRepository::upsert()`, so completion hooks, snapshots, and drip-cache invalidation still run. It is an administrative override of learner quiz and drip gates; do not replace it with raw SQL.
- Trust `OutputSchemas` over the older prose docs when shape details differ; v1.2.16 added `total_pages`, `page`, and `per_page` to `list-courses`.
## Common mistakes
```bash
# WRONG: LMS learner REST namespace, not an ability run route.
curl -X POST "${SITE_URL}/wp-json/lms/v1/get-progress"
# RIGHT:
curl -X POST "${SITE_URL}/wp-json/wp-abilities/v1/abilities/lw-lms/get-progress/run" \
-d '{"input":{"user_id":7,"course_id":42}}'
```
```php
// WRONG: assume Site Manager must be active.
if ( ! class_exists( '\LightweightPlugins\SiteManager\Plugin' ) ) {
return;
}
// RIGHT: check the ability/API you actually need.
if ( function_exists( 'wp_get_ability' ) && wp_get_ability( 'lw-lms/list-courses' ) ) {
// Call it.
}
```
## Cross-references
- Run `lw-lms-backend-extend` when adding companion hooks around enrollment, access, or progress.
- Run `lw-site-manager-overview` when consuming the broader `site-manager/*` ability surface.
- Run `wp-abilities-api` for the underlying WordPress Abilities API mechanics.
## What this skill does NOT cover
- Public learner UI and course rendering. Use `lw-lms-rest-frontend` for the core REST API contract.
- Registering arbitrary third-party Site Manager abilities. Use `lw-site-manager-extend-abilities`.
- LearnDash migration. Use `lw-lms-learndash-migration`.
## References
- Registration bridge and fallback: `includes/SiteManager/Integration.php`.
- Ability definitions: `includes/SiteManager/Abilities/CourseAbilities.php`, `ProgressAbilities.php`, `OptionsAbilities.php`.
- Permission fallback: `includes/SiteManager/Abilities/AbilityPermissions.php`.
- Output schemas: `includes/SiteManager/Schema/OutputSchemas.php`.
- Service behavior and `WP_Error` codes: `includes/SiteManager/Service/`.
- Official documentation: <https://github.com/lwplugins/lw-lms>
- Official documentation: <https://developer.wordpress.org/apis/abilities-api/>
- Verified source paths:
- `includes/SiteManager/Abilities/AbilityMeta.php`
- `docs/site-manager-abilities.md`