DocsThe APIMCP

MCP

A remote MCP server so Claude, Cursor, and other MCP clients can create and manage courses as tools — the same operations as the REST API, callable from a conversation.

Connect

Point any MCP client that speaks Streamable HTTP at this URL, with your API key as a Bearer token — the same key from your workspace's API Keys page. Every tool call is scoped to that key's workspace, exactly like the REST API.

Claude Desktop / Cursor mcpServers configjson
{
  "underlayer": {
    "url": "https://underlayer.outworx.io/api/mcp",
    "headers": {
      "Authorization": "Bearer sk_live_..."
    }
  }
}

For stdio-only clients that can't reach a remote URL directly, bridge it with mcp-remote:

stdio bridgejson
{
  "underlayer": {
    "command": "npx",
    "args": ["-y", "mcp-remote", "https://underlayer.outworx.io/api/mcp",
      "--header", "Authorization:Bearer sk_live_..."]
  }
}

OAuth, for Claude.ai and other web clients

Claude.ai's browser-based “Add custom connector” flow can't paste in a Bearer header — it authenticates with OAuth instead. Underlayer is its own authorization server for this: add https://underlayer.outworx.io/api/mcp as a custom connector and Claude discovers everything else automatically (RFC 9728 protected-resource metadata → RFC 8414 authorization-server metadata → an authorization-code + PKCE flow, using CIMD to identify itself — no manual client registration on your end).

You'll land on a sign-in screen (if you're not already signed in) and then a consent screen naming the connecting app and your workspace. Approving it grants the same access an API key would — full create/read/update/delete on everything below. Revoke it anytime from Connected Apps in your dashboard; access stops immediately.

One thing that access does not include: minting API keys. A key is a separate credential rather than a view onto this connection, so one created through a connector would keep working after you revoked the connector — access outliving its own revocation. Keys are issued only from the API Keys page, where a person is looking at the screen. Listing and revoking are available as tools, since neither creates access.

Tools

Every REST resource is exposed as a matching set of tools — same validation, same plan gates, same ownership checks. Results come back as JSON.

Authoring tools write; the progress tools only read. That asymmetry is deliberate: a completion is a record of something a real person did, and a tool that could edit one would be a tool that could award a pass.

Courses
list_coursesget_coursecreate_courseupdate_coursedelete_course
Screens & blocks
list_block_typeslist_screen_templatesadd_screenupdate_screenadd_blockduplicate_screendelete_screenreorder_screens
AI generationBUILD PLAN
generate_courseget_generation
SCORMSCALE PLAN
export_scormimport_scorm
ThemesSCALE PLAN
list_themesget_themecreate_themeupdate_themedelete_theme
Collections
list_collectionsget_collectioncreate_collectionupdate_collectiondelete_collectionadd_course_to_collectionmove_course_in_collectionremove_course_from_collection
TranslationsSCALE PLAN
list_translationsget_translationcreate_translationupdate_translationdelete_translation
Webhooks
list_webhooksget_webhookcreate_webhookupdate_webhookdelete_webhook
Certificate templatesSCALE PLAN
list_certificatesget_certificatecreate_certificateupdate_certificatedelete_certificate
Identities
list_identitiesget_identityupsert_identitybulk_upsert_identitiesdelete_identitybulk_delete_identities
Learner progressREAD-ONLY
list_completionsget_completionlist_issued_certificatesget_issued_certificate
ReportingREAD-ONLY
get_overviewsearch_contentget_usagelist_audit_events
Team & credentials
list_membersinvite_membercancel_inviteupdate_member_roleremove_memberlist_api_keysrevoke_api_key
Workspace
get_workspace_infoupdate_workspace_settings

list_completions takes identityExternalId, so you can ask about a learner by your own id for them without looking ours up first, and get_issued_certificate accepts a serial however it was typed — case and dashes are normalised, because the serial usually arrives read off a piece of paper.

Prefer the screen tools over update_course for editing content. update_course can only write the whole screens array, so changing one screen of thirty means reading them all back and rewriting the lot — and two edits in flight lose one of them. update_screen does the read-modify-write server-side, on one screen. Start from list_block_types: a block with the wrong field names saves cleanly and then renders empty.

Auth and errors

Every request re-authenticates with the same Bearer key as the REST API — a missing or revoked key fails the connection outright. A tool-level problem (not found, invalid input, plan required) comes back as a normal tool result with isError: true and a human-readable message, not a broken connection.

Actions that change who can get in — inviting, removing, changing a role, revoking a key, renaming the workspace — are written to the audit log naming the key that made them, so an automated change is as traceable as a human one. Read it back with list_audit_events or from Settings in the dashboard.