Add LMS MCP write tools - #122
Merged
Merged
Conversation
Give AI clients a package-local stdio server to create and edit Course → Lesson → Step data from hosted YouTube/Vimeo URLs, with new courses private by default. Co-authored-by: Cursor <cursoragent@cursor.com>
Keep the MCP Unreleased entry and the released v4.7.7 dashboard changelog. Co-authored-by: Cursor <cursoragent@cursor.com>
Require isLmsAdmin for authenticated MCP writes, guard tenant context when tenancy is enabled, prefix auto external_ids that start with a digit, and assert on JSON-safe video fields in LmsMcpTest. Co-authored-by: Cursor <cursoragent@cursor.com>
Assert on the video id and provider name instead of exact JSON key spacing. Co-authored-by: Cursor <cursoragent@cursor.com>
HTTP MCP requests have no Filament panel, and Spatie sortable was using a global max, so new courses got null admin/learner links and order 34/83. Co-authored-by: Cursor <cursoragent@cursor.com>
Keep MCP registration through the certificate-template and user-group work on 4.x, and fix slug collisions, lesson order shifts, and update_step validation. Co-authored-by: Cursor <cursoragent@cursor.com>
Contributor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 5f83df5. Configure here.
prefer-stable laravel/mcp leaves slashes unescaped, so the old admin\/lms path check failed CI. Co-authored-by: Cursor <cursoragent@cursor.com>
…pdate. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Hosts still add HasApiTokens and the tokens table; the package now mounts the route, admin gate, rate limit, and token command. Co-authored-by: Cursor <cursoragent@cursor.com>
Package README and tests should describe any host, not one project. Co-authored-by: Cursor <cursoragent@cursor.com>
Contributor
Author
|
@swilla I've updated this package to minimize the amount of work that projects need to do to start using the MCP:
they no longer need to define and auth an /mcp/lms route. its published by the package and uses sanctum and isLmsAdmin for authorization |
Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Add a Laravel MCP server so hosts can create and edit Course → Lesson → video Step data over stdio or HTTP, and fix null Filament URLs and global Spatie sort order on new courses.
Design decisions
The package registers POST /mcp/lms on by default
Why
Hosts should not copy a route after an LMS update. The route is Sanctum,
throttle:mcp, andisLmsAdmin(). The leftover isHasApiTokens, the tokens table, a realisLmsAdmin(), and pasting the bearer into Claude.High impact
Every app that upgrades this package gets a public write endpoint unless they set
filament-lms.mcp.webtofalse. Hosts whoseisLmsAdmin()stays the defaultfalseget 403.Files
src/FilamentLmsServiceProvider.php
src/Http/Middleware/EnsureLmsMcpAdmin.php
src/Console/Commands/LmsMcpTokenCommand.php
Set the Filament panel before generating MCP URLs
Why
HTTP MCP requests have no current panel, so
CourseResource::getUrlandStepPage::getUrlForStepthrew andsafeUrl()returned null. Tool payloads listedurls.adminandurls.learneras null.Files
src/Mcp/LmsTool.php
Scope Spatie sort order to the parent course or lesson
Why
SortableTraitused a globalmax(order) + 1. A new course inherited the highest lesson and step order in the database.buildSortQuery()scopes Lesson tocourse_idand Step tolesson_id.Files
src/Models/Lesson.php
src/Models/Step.php
Testing
Already verified on a local Filament-LMS clone and against CHECK staging (
https://check.webuildawesomesoftware.com/mcp/lms).POST /mcp/lmswith no token → 401. A Sanctum user whoseisLmsAdmin()is false → 403.list_coursesorget_courseas an LMS admin.urls.adminandurls.learnerare Filament paths, not null.create_video_coursefor a private throwaway. First lesson and first step areorder: 1. Delete that course.Note
High Risk
Upgrading hosts get a default public MCP write route unless
filament-lms.mcp.webis false; compromise of an LMS-admin Sanctum token allows course structure mutations over HTTP.Overview
Adds a Laravel MCP server so AI clients can read and write LMS structure (Course → Lesson → YouTube/Vimeo video Step) over local stdio (
php artisan mcp:start filament-lms) or HTTP atPOST /mcp/lms. The package now requireslaravel/mcpandlaravel/sanctum, registers both transports by default (filament-lms.mcp.enabled/mcp.web), and protects HTTP with Sanctum,throttle:mcp, andisLmsAdmin().php artisan lms:mcp-tokenmints bearer tokens and prints Claude Desktop config; README documents Cursor/Claude Code setup.v1 tools include
create_video_course(nested create, private by default) plus granular list/get/update/delete for courses, lessons, and video steps. SharedLmsToollogic handles tenancy, Filament-aligned validation (certificate_template_id, unique fields), embed URL conversion, and admin/learner URLs by temporarily setting the correct Filament panel.Model fixes scope Spatie lesson/step ordering to
course_id/lesson_id, prefix auto step slugs with the course slug, and shift lesson order when inserting at an explicit position. MCPupdate_stepvalidates video URLs and refuses to turn non-video steps into video steps.Reviewed by Cursor Bugbot for commit 83e0b8c. Bugbot is set up for automated code reviews on this repo. Configure here.