chore: update @tanstack/react-start dependency to version 1.143.4 and add MCP documentation
This commit is contained in:
@@ -0,0 +1,306 @@
|
|||||||
|
---
|
||||||
|
title: MCP
|
||||||
|
description: Connect Claude Code, Codex, Cursor, and other MCP clients to ClassroomIO for draft-based course authoring.
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Callout } from 'fumadocs-ui/components/callout';
|
||||||
|
|
||||||
|
`@classroomio/mcp` is a thin stdio MCP server for ClassroomIO course authoring.
|
||||||
|
|
||||||
|
It does not parse PDFs or generate course structures itself. The agent does that work. The MCP
|
||||||
|
server exposes tools, validates tool input, and forwards authenticated requests to the
|
||||||
|
ClassroomIO API.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```text
|
||||||
|
Teacher / Admin
|
||||||
|
|
|
||||||
|
v
|
||||||
|
Claude Code / Codex / Cursor / other MCP client
|
||||||
|
|
|
||||||
|
| 1. Reads prompt, PDF, or existing course goal
|
||||||
|
| 2. Produces or edits normalized course JSON
|
||||||
|
v
|
||||||
|
@classroomio/mcp (stdio)
|
||||||
|
|
|
||||||
|
| 3. Sends authenticated tool calls
|
||||||
|
| Authorization: Bearer <cio_mcp_...>
|
||||||
|
v
|
||||||
|
ClassroomIO API
|
||||||
|
|
|
||||||
|
| 4. Validates payloads
|
||||||
|
| 5. Resolves the organization from the key
|
||||||
|
| 6. Creates drafts or applies changes to a course
|
||||||
|
v
|
||||||
|
ClassroomIO DB
|
||||||
|
```
|
||||||
|
|
||||||
|
## Core Principles
|
||||||
|
|
||||||
|
1. The agent owns reasoning.
|
||||||
|
2. The MCP package owns transport and input validation.
|
||||||
|
3. ClassroomIO API remains the trust boundary for auth, validation, and persistence.
|
||||||
|
4. Draft creation and publish are separate operations.
|
||||||
|
5. Updating an existing course is done through a seeded draft, not blind writes to the live
|
||||||
|
course.
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
Generate an org-scoped MCP key from `Automation -> MCP` in the ClassroomIO dashboard.
|
||||||
|
|
||||||
|
The MCP process sends that key as a bearer token on every request.
|
||||||
|
|
||||||
|
ClassroomIO API:
|
||||||
|
|
||||||
|
1. hashes and verifies the key
|
||||||
|
2. resolves the owning organization
|
||||||
|
3. checks the key scopes
|
||||||
|
4. executes the requested action
|
||||||
|
|
||||||
|
The MCP package never decides permissions.
|
||||||
|
|
||||||
|
## Required Environment Variables
|
||||||
|
|
||||||
|
- `CLASSROOMIO_API_URL`
|
||||||
|
- `CLASSROOMIO_API_KEY`
|
||||||
|
- `CLASSROOMIO_USER_AGENT` optional
|
||||||
|
|
||||||
|
## Run the MCP Server
|
||||||
|
|
||||||
|
Published package:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
CLASSROOMIO_API_URL=https://api.classroomio.com \
|
||||||
|
CLASSROOMIO_API_KEY=<cio_mcp_key> \
|
||||||
|
npx -y @classroomio/mcp
|
||||||
|
```
|
||||||
|
|
||||||
|
From the monorepo:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm build --filter=@classroomio/mcp
|
||||||
|
CLASSROOMIO_API_URL=http://localhost:3081 \
|
||||||
|
CLASSROOMIO_API_KEY=<cio_mcp_key> \
|
||||||
|
node packages/mcp/dist/index.js
|
||||||
|
```
|
||||||
|
|
||||||
|
## Client Setup
|
||||||
|
|
||||||
|
### Claude Code
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude mcp add-json classroomio '{
|
||||||
|
"command": "npx",
|
||||||
|
"args": ["-y", "@classroomio/mcp"],
|
||||||
|
"env": {
|
||||||
|
"CLASSROOMIO_API_URL": "https://api.classroomio.com",
|
||||||
|
"CLASSROOMIO_API_KEY": "<cio_mcp_key>"
|
||||||
|
}
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Codex
|
||||||
|
|
||||||
|
```bash
|
||||||
|
codex mcp add classroomio \
|
||||||
|
--env CLASSROOMIO_API_URL=https://api.classroomio.com \
|
||||||
|
--env CLASSROOMIO_API_KEY=<cio_mcp_key> \
|
||||||
|
-- npx -y @classroomio/mcp
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cursor
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"classroomio": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": ["-y", "@classroomio/mcp"],
|
||||||
|
"env": {
|
||||||
|
"CLASSROOMIO_API_URL": "https://api.classroomio.com",
|
||||||
|
"CLASSROOMIO_API_KEY": "<cio_mcp_key>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tool Surface
|
||||||
|
|
||||||
|
Current tools:
|
||||||
|
|
||||||
|
- `list_org_courses`
|
||||||
|
- `get_course_structure`
|
||||||
|
- `update_course_landing_page`
|
||||||
|
- `create_course_draft`
|
||||||
|
- `create_course_draft_from_course`
|
||||||
|
- `get_course_draft`
|
||||||
|
- `update_course_draft`
|
||||||
|
- `publish_course_draft`
|
||||||
|
- `publish_course_draft_to_existing_course`
|
||||||
|
- `tag_course_draft`
|
||||||
|
- `tag_courses`
|
||||||
|
- `list_course_exercises`
|
||||||
|
- `get_course_exercise`
|
||||||
|
- `create_course_exercise`
|
||||||
|
- `create_course_exercise_from_template`
|
||||||
|
- `update_course_exercise`
|
||||||
|
|
||||||
|
## Draft Model
|
||||||
|
|
||||||
|
A draft is a saved, structured course proposal. It is not the live course.
|
||||||
|
|
||||||
|
Draft payload shape:
|
||||||
|
|
||||||
|
```text
|
||||||
|
draft
|
||||||
|
course
|
||||||
|
tags[]
|
||||||
|
sections[]
|
||||||
|
lessons[]
|
||||||
|
lessonLanguages[]
|
||||||
|
warnings[]
|
||||||
|
sourceReferences[] optional
|
||||||
|
exercises[] optional
|
||||||
|
```
|
||||||
|
|
||||||
|
Drafts support:
|
||||||
|
|
||||||
|
- review before publish
|
||||||
|
- iterative edits from the agent
|
||||||
|
- safer updates to existing courses
|
||||||
|
- auditability of AI-generated structure
|
||||||
|
|
||||||
|
## Create a New Course
|
||||||
|
|
||||||
|
Typical flow:
|
||||||
|
|
||||||
|
1. Agent plans the course.
|
||||||
|
2. Agent calls `create_course_draft`.
|
||||||
|
3. User asks for revisions.
|
||||||
|
4. Agent calls `update_course_draft`.
|
||||||
|
5. User approves.
|
||||||
|
6. Agent calls `publish_course_draft`.
|
||||||
|
|
||||||
|
Publish returns:
|
||||||
|
|
||||||
|
- `courseId`
|
||||||
|
- `courseUrl`
|
||||||
|
- `bannerImageUrl` when a banner was explicitly provided or generated
|
||||||
|
- `tagNames`
|
||||||
|
|
||||||
|
`publish_course_draft` can also:
|
||||||
|
|
||||||
|
- use an explicit `bannerImageUrl`
|
||||||
|
- generate a random Unsplash-based banner from the course title or a custom query
|
||||||
|
|
||||||
|
## Update an Existing Course
|
||||||
|
|
||||||
|
When the course already exists, use the live course as the source of truth.
|
||||||
|
|
||||||
|
Recommended sequence:
|
||||||
|
|
||||||
|
1. `list_org_courses` if the agent needs to resolve the course ID by name
|
||||||
|
2. `get_course_structure`
|
||||||
|
3. `create_course_draft_from_course`
|
||||||
|
4. `update_course_draft`
|
||||||
|
5. `publish_course_draft_to_existing_course`
|
||||||
|
|
||||||
|
This avoids applying broad, blind changes directly to the live course.
|
||||||
|
|
||||||
|
## Update a Course Landing Page
|
||||||
|
|
||||||
|
Use `update_course_landing_page` when the user wants AI help with sales-page style content on an
|
||||||
|
already-existing course.
|
||||||
|
|
||||||
|
This tool can update:
|
||||||
|
|
||||||
|
- title
|
||||||
|
- short description
|
||||||
|
- overview
|
||||||
|
- requirements
|
||||||
|
- goals
|
||||||
|
- pricing fields
|
||||||
|
- instructor section
|
||||||
|
- reviews
|
||||||
|
- the landing-page image
|
||||||
|
|
||||||
|
For images, the tool supports either:
|
||||||
|
|
||||||
|
- `imageUrl` for an explicit cover image
|
||||||
|
- `generateImage` and `imageQuery` for a random Unsplash-derived image
|
||||||
|
|
||||||
|
## After Publish
|
||||||
|
|
||||||
|
Once a draft has been published, the live course becomes the safer source of truth.
|
||||||
|
|
||||||
|
Recommended agent rule:
|
||||||
|
|
||||||
|
- if the draft is still `DRAFT`, continue editing that draft
|
||||||
|
- if the draft is `PUBLISHED`, do not keep reusing it for major follow-up edits
|
||||||
|
- instead, read the live course and create a fresh draft from that course
|
||||||
|
|
||||||
|
Why:
|
||||||
|
|
||||||
|
- teachers may edit the live course in the UI after publish
|
||||||
|
- another agent session may have changed the course
|
||||||
|
- reusing an old published draft can overwrite newer live changes
|
||||||
|
|
||||||
|
## Exercises on Live Courses
|
||||||
|
|
||||||
|
If the user only wants to add or revise exercises on a published course, prefer the direct
|
||||||
|
exercise tools instead of creating a whole new draft:
|
||||||
|
|
||||||
|
- `list_course_exercises`
|
||||||
|
- `get_course_exercise`
|
||||||
|
- `create_course_exercise`
|
||||||
|
- `create_course_exercise_from_template`
|
||||||
|
- `update_course_exercise`
|
||||||
|
|
||||||
|
Use a draft only when the agent is restructuring broader course content.
|
||||||
|
|
||||||
|
Supported `questionTypeId` values for exercise payloads:
|
||||||
|
|
||||||
|
- `1` `RADIO` - Single answer
|
||||||
|
- `2` `CHECKBOX` - Multiple answers
|
||||||
|
- `3` `TEXTAREA` - Paragraph
|
||||||
|
- `4` `TRUE_FALSE` - True/False
|
||||||
|
- `5` `SHORT_ANSWER` - Short answer
|
||||||
|
- `6` `NUMERIC` - Numeric answer
|
||||||
|
- `7` `FILL_BLANK` - Fill in the blank
|
||||||
|
- `8` `FILE_UPLOAD` - File upload
|
||||||
|
- `9` `MATCHING` - Matching
|
||||||
|
- `10` `ORDERING` - Ordering
|
||||||
|
- `11` `HOTSPOT` - Hotspot
|
||||||
|
- `12` `LINK` - Links
|
||||||
|
|
||||||
|
## Tagging
|
||||||
|
|
||||||
|
The MCP supports tagging at two levels:
|
||||||
|
|
||||||
|
- `tag_course_draft`
|
||||||
|
- set or revise tags before publish
|
||||||
|
- `tag_courses`
|
||||||
|
- tag one or more live courses
|
||||||
|
|
||||||
|
The live-course tagging tool supports merge-or-replace behavior. Use merge when the user wants to
|
||||||
|
add tags without removing existing ones.
|
||||||
|
|
||||||
|
## PDF-Based Authoring
|
||||||
|
|
||||||
|
If a user wants to turn a PDF into a course:
|
||||||
|
|
||||||
|
1. the agent reads and extracts the PDF itself
|
||||||
|
2. the agent converts the content into normalized course JSON
|
||||||
|
3. the agent calls `create_course_draft`
|
||||||
|
4. the user reviews the draft
|
||||||
|
5. the agent publishes it
|
||||||
|
|
||||||
|
The PDF itself is not uploaded to the MCP server.
|
||||||
|
|
||||||
|
<Callout title="Operational Rule">
|
||||||
|
Keep published drafts for history and auditability. Do not treat omission from a draft as an
|
||||||
|
instruction to delete live sections or lessons. Destructive changes should only happen through
|
||||||
|
explicit user intent.
|
||||||
|
</Callout>
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
"---Core Features---",
|
"---Core Features---",
|
||||||
"course",
|
"course",
|
||||||
|
"mcp",
|
||||||
"tags",
|
"tags",
|
||||||
"audience",
|
"audience",
|
||||||
"community",
|
"community",
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tanstack/react-router": "^1.134.12",
|
"@tanstack/react-router": "^1.134.12",
|
||||||
"@tanstack/react-router-devtools": "^1.134.12",
|
"@tanstack/react-router-devtools": "^1.134.12",
|
||||||
"@tanstack/react-start": "^1.134.12",
|
"@tanstack/react-start": "^1.143.4",
|
||||||
"fumadocs-core": "16.2.1",
|
"fumadocs-core": "16.2.1",
|
||||||
"fumadocs-mdx": "14.0.4",
|
"fumadocs-mdx": "14.0.4",
|
||||||
"fumadocs-ui": "16.2.1",
|
"fumadocs-ui": "16.2.1",
|
||||||
|
|||||||
Reference in New Issue
Block a user