Concepts & architecture
The pieces
Section titled “The pieces”Claude / MCP client ──(Bearer key)──▶ openedxmcp container (MCP proxy) │ X-MCP-Key ┌───────────┴───────────┐ LMS /api/mcp/ CMS /api/mcp/cms/ (people, enroll, (course authoring, analytics, certs, modulestore) reports, retire)- MCP server (
tutor-contrib-openedxmcp) — a stateless MCP streamable-http proxy, fronted by Caddy atmcp.<LMS_HOST>. It holds no secrets; each request carries its own key, forwarded asX-MCP-Key. - Facade (
openedx-mcp) — a standard Open edX djangoapp plugin exposing the REST endpoints and enforcing all authorization. Installed into the openedx image.
Why two processes
Section titled “Why two processes”Course-authoring APIs write the modulestore, which is only writable in the
CMS/Studio process, so authoring tools mount at /api/mcp/cms/. Everything
else — people, access, enrollment, analytics, certificates, reports — runs in the
LMS at /api/mcp/. One Django app ships both AppConfigs and shares one key
table.
Native only
Section titled “Native only”Every operation calls importable openedx-platform functions — no core fork, no
vendored logic, no third-party stack. That keeps the plugin upgradable with the
platform and trustworthy to run against a production instance.
Authorization in one line
Section titled “Authorization in one line”The platform’s own is_staff / is_superuser is the sole authority, re-checked
live on every request. MCP keys are Django models; scopes only narrow what an
already-privileged user may do through a given credential. See
Security & scopes.