API & MCP · MCP setup
MCP server setup
EMPO Academy speaks Model Context Protocol so any MCP-compatible AI client — Claude Desktop, Cursor, the Claude API SDK, OpenAI Agents SDK — can drive the platform through a selected subset of the documented REST endpoints. New guarded authoring mutations are REST/CLI-only and are not exposed as MCP tools.
Two transports
- Hosted Streamable HTTP — you point the client at
https://academy.empomm.com/api/mcpwith a bearer token. Zero install. Each tool call goes over the network. Subject to the same per-key (60/min) and per-IP (120/min) rate limits as the REST API, plus a 500 KB body cap per request (413 on overflow — split big tool inputs across multiple calls). - Local stdio — you install the
@empo-academy/mcp-serverpackage once and your client spawns it as a subprocess. The tool calls still hit the hosted REST API under the hood, so the same rate limits apply.
Both end up calling the same REST API. Pick whichever your client supports best. The MCP surface is intentionally a selected subset; use the REST/CLI clients for every documented authoring mutation.
Claude Desktop (hosted)
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"empo-academy": {
"url": "https://academy.empomm.com/api/mcp",
"transport": "streamable-http",
"headers": {
"Authorization": "Bearer empo_xxxxxxxxxxxxxxxxxxxx"
}
}
}
}Restart Claude Desktop. New conversations get an EMPO tool list.
Claude Desktop (stdio)
- Clone the repo and build the package:
cd packages/empo-mcp && npm install && npm run build - Point Claude Desktop at the built binary:
{
"mcpServers": {
"empo-academy": {
"command": "node",
"args": ["/absolute/path/to/packages/empo-mcp/dist/index.js"],
"env": {
"EMPO_API_KEY": "empo_xxxxxxxxxxxxxxxxxxxx",
"EMPO_BASE_URL": "https://academy.empomm.com"
}
}
}
}Cursor
Open Cursor settings → MCP → Add server. The Cursor MCP UI accepts the same JSON shape as Claude Desktop. Use the hosted URL for the simplest setup.
Claude API SDK / OpenAI Agents SDK
Both SDKs ship an MCP client. Point them at the hosted endpoint with the bearer token and you’re done. They receive the selected MCP tool subset with the same scope and ownership checks.
Tool reference
The tools below are the currently selected MCP subset (and their MCP Tool Annotations). Annotations are hints clients use to decide whether to prompt for confirmation; the server still enforces everything via scope + role checks regardless. REST-only authoring routes are listed on the endpoint page but do not appear here.
empo_me,empo_list_courses,empo_get_course,empo_list_notification_templates—readOnlyHint: trueempo_create_course,empo_update_course,empo_create_module,empo_create_lesson,empo_issue_training_certificate,empo_issue_training_certificate_batch,empo_resend_certificate_email,empo_update_notification_template— standard mutationsempo_set_course_status,empo_revoke_certificate—destructiveHint: true(Claude prompts before running)
Troubleshooting
- 401 from MCP endpoint: bearer token missing, malformed, expired, or revoked. Check /dashboard/api-keys.
- 403 MISSING_SCOPE: the key doesn’t include the scope the tool needs. Mint a new key with the right scope or add it.
- 403 FORBIDDEN: the underlying record (course, cert) isn’t owned by your user. Instructor keys can only act on their own courses (or courses where they’re a collaborator).
- 413 PAYLOAD_TOO_LARGE: request body exceeded the 500 KB cap. Common cause: pasting an entire markdown course into
empo_scaffold_course. Split the work — one course-shell call, then per-lessonempo_blocks_from_markdowncalls. - 429 RATE_LIMITED: you’ve hit the per-key (60/min) or per-IP (120/min) bucket. Back off on
Retry-Afterseconds; don’t loop blindly. If a legitimate integration needs more headroom, email academy@empomm.com. - Diagnose any of the above: open the offending key’s usage at
/dashboard/api-keys/<id>/usage— the last 25 calls show method/path/status/duration with the last error highlighted.