Skip to content

Concepts & architecture

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 at mcp.<LMS_HOST>. It holds no secrets; each request carries its own key, forwarded as X-MCP-Key.
  • Facade (openedx-mcp) — a standard Open edX djangoapp plugin exposing the REST endpoints and enforcing all authorization. Installed into the openedx image.

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.

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.

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.