MCP Server for LearnHouse LMS - Manage courses, chapters, activities, and users
npm install learnhouse-mcp-server
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β VS Code / AI Agent β
β (GitHub Copilot, Claude, etc.) β
βββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββ
β stdio (JSON-RPC)
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LearnHouse MCP Server β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β FastMCP Framework β β
β β βββββββββββ βββββββββββ βββββββββββ ββββββββββββββββββββ β
β β β Course β β Chapter β βActivity β β Progress/Search ββ β
β β β Tools β β Tools β β Tools β β Tools ββ β
β β ββββββ¬βββββ ββββββ¬βββββ ββββββ¬βββββ ββββββββββ¬ββββββββββ β
β βββββββββΌββββββββββββΌββββββββββββΌββββββββββββββββΌββββββββββ β
β β β β β β
β βββββββββ΄ββββββββββββ΄ββββββββββββ΄ββββββββββββββββ΄ββββββββββ β
β β LearnHouseClient (API Wrapper) β β
β β β’ Authentication (login, token management) β β
β β β’ HTTP Methods (GET, POST, PUT, DELETE) β β
β β β’ Error Handling β β
β βββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββ β
ββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββ
β HTTPS
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LearnHouse API (FastAPI) β
β http://localhost:3000 β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
`
$3
| Component | File | Description |
| -------------------- | ------------------ | --------------------------------- |
| MCP Server | src/index.ts | Tool definitions with Zod schemas |
| API Client | src/client.ts | LearnHouseClient wrapper class |
| Type Definitions | src/types.ts | TypeScript interfaces & enums |
| Configuration | .vscode/mcp.json | VS Code MCP server config |
---
Installation & Setup
$3
- Node.js 18+
- pnpm (or npm/yarn)
- LearnHouse instance with admin credentials
- VS Code with GitHub Copilot (for integration)
$3
`bash
cd .mcp
pnpm install
`
$3
`bash
pnpm build
`
$3
`bash
pnpm dev
`
$3
`bash
Inspect available tools
pnpm inspect
Run API tests
pnpm test
`
---
Configuration
$3
| Variable | Description | Default |
| --------------------- | ------------------------------ | ----------------------- |
| LEARNHOUSE_URL | Base URL of LearnHouse API | http://localhost:3000 |
| LEARNHOUSE_EMAIL | Admin email for authentication | Required |
| LEARNHOUSE_PASSWORD | Admin password | Required |
| LEARNHOUSE_ORG_ID | Organization ID | 1 |
$3
The MCP server is configured in .vscode/mcp.json:
`json
{
"servers": {
"learnhouse": {
"command": "npx",
"args": ["tsx", "${workspaceFolder}/.mcp/src/index.ts"],
"env": {
"LEARNHOUSE_URL": "http://localhost:3000",
"LEARNHOUSE_EMAIL": "admin@example.com",
"LEARNHOUSE_PASSWORD": "YourPassword",
"LEARNHOUSE_ORG_ID": "1"
}
}
}
}
`
---
Available Tools
$3
| Tool | Description | Parameters |
| --------------- | ------------------------------------ | ---------------------------------------------------- |
| list_courses | List all courses in the organization | page?, limit? |
| get_course | Get detailed course information | course_uuid |
| create_course | Create a new course | name, description, public? |
| update_course | Update an existing course | course_uuid, name?, description?, published? |
| delete_course | Delete a course | course_uuid |
$3
| Tool | Description | Parameters |
| ---------------- | ----------------------------- | ---------------------------------------------- |
| list_chapters | List all chapters in a course | course_id |
| get_chapter | Get chapter details | chapter_id |
| create_chapter | Create a new chapter | course_id, name, description?, org_id? |
| update_chapter | Update a chapter | chapter_id, name?, description? |
$3
| Tool | Description | Parameters |
| ---------------------- | -------------------------------- | -------------------------------------------------------------------------- |
| list_activities | List all activities in a chapter | chapter_id |
| get_activity | Get activity details | activity_uuid |
| create_activity | Create a new activity | chapter_id, name, activity_type?, activity_sub_type?, published? |
| update_activity | Update an activity | activity_uuid, name?, published? |
| publish_activity | Publish an activity | activity_uuid |
| set_document_content | Set TipTap document content | activity_uuid, content (JSON string) |
$3
| Tool | Description | Parameters |
| ------------------- | -------------------------- | ---------------------------- |
| set_video_content | Set video URL for activity | activity_uuid, video_url |
$3
| Tool | Description | Parameters |
| ------------------ | --------------------------- | ---------- |
| get_current_user | Get authenticated user info | None |
| get_organization | Get organization details | org_id? |
$3
| Tool | Description | Parameters |
| ------------------------ | -------------------------- | --------------- |
| get_course_progress | Get user's course progress | course_uuid |
| mark_activity_complete | Mark activity as completed | activity_uuid |
$3
| Tool | Description | Parameters |
| -------- | -------------------------- | -------------------- |
| search | Search courses and content | query, org_slug? |
---
Data Models
$3
`typescript
enum ActivityType {
TYPE_DYNAMIC = "TYPE_DYNAMIC", // Rich text document (TipTap)
TYPE_VIDEO = "TYPE_VIDEO", // Video content
TYPE_DOCUMENT = "TYPE_DOCUMENT", // PDF or document
TYPE_ASSIGNMENT = "TYPE_ASSIGNMENT", // Assignment
TYPE_CUSTOM = "TYPE_CUSTOM", // Custom type
}
enum ActivitySubType {
SUBTYPE_DYNAMIC_PAGE = "SUBTYPE_DYNAMIC_PAGE", // TipTap editor page
SUBTYPE_VIDEO_YOUTUBE = "SUBTYPE_VIDEO_YOUTUBE", // YouTube embed
SUBTYPE_VIDEO_HOSTED = "SUBTYPE_VIDEO_HOSTED", // Self-hosted video
SUBTYPE_DOCUMENT_PDF = "SUBTYPE_DOCUMENT_PDF", // PDF viewer
SUBTYPE_DOCUMENT_DOC = "SUBTYPE_DOCUMENT_DOC", // Document
}
`
$3
LearnHouse uses TipTap as its rich text editor. Content is stored as JSON:
`json
{
"type": "doc",
"content": [
{
"type": "heading",
"attrs": { "level": 1 },
"content": [{ "type": "text", "text": "Welcome" }]
},
{
"type": "paragraph",
"content": [{ "type": "text", "text": "This is a paragraph." }]
},
{
"type": "bulletList",
"content": [
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [{ "type": "text", "text": "Item 1" }]
}
]
}
]
}
]
}
`
$3
`
Organization (org_id: 1)
βββ Course (course_uuid)
βββ name: string
βββ description: string
βββ public: boolean
βββ published: boolean
βββ chapters[]
βββ Chapter (chapter_id, chapter_uuid)
βββ name: string
βββ description: string
βββ activities[]
βββ Activity (activity_uuid)
βββ name: string
βββ activity_type: ActivityType
βββ activity_sub_type: ActivitySubType
βββ content: TipTapDocument | VideoContent
βββ published: boolean
`
---
Usage Examples
$3
`
User: Create a course called "Python Fundamentals" with two chapters
AI Agent (using MCP tools):
1. create_course(name: "Python Fundamentals", description: "Learn Python basics")
β Returns course_uuid: "course_abc123"
2. create_chapter(course_id: 15, name: "Getting Started")
β Returns chapter_id: 70
3. create_chapter(course_id: 15, name: "Variables & Data Types")
β Returns chapter_id: 71
4. create_activity(chapter_id: 70, name: "Introduction to Python", activity_type: "TYPE_DYNAMIC")
β Returns activity_uuid: "activity_xyz789"
5. set_document_content(activity_uuid: "activity_xyz789", content: {...tiptap json...})
β Content saved
6. publish_activity(activity_uuid: "activity_xyz789")
β Activity published
`
$3
`
User: Add a YouTube tutorial to chapter 70
AI Agent (using MCP tools):
1. create_activity(
chapter_id: 70,
name: "Python Tutorial Video",
activity_type: "TYPE_VIDEO",
activity_sub_type: "SUBTYPE_VIDEO_YOUTUBE"
)
β Returns activity_uuid: "activity_video123"
2. set_video_content(
activity_uuid: "activity_video123",
video_url: "https://www.youtube.com/watch?v=example"
)
β Video URL set
3. publish_activity(activity_uuid: "activity_video123")
β Published
`
$3
`
User: Find all courses about MCP and update their descriptions
AI Agent (using MCP tools):
1. search(query: "MCP")
β Returns: [{course_uuid: "course_mcp1", name: "MCP Introduction"}]
2. update_course(
course_uuid: "course_mcp1",
description: "Updated description for MCP course"
)
β Course updated
`
---
VS Code Integration
$3
1. VS Code loads mcp.json at startup
2. Starts the MCP server as a subprocess
3. Tools become available to GitHub Copilot
4. AI agent discovers tools via MCP protocol
5. Tools execute and return results
$3
In VS Code:
1. Open Command Palette (Ctrl+Shift+P)
2. Run "Developer: Show MCP Tools"
3. You should see all 21 LearnHouse tools
$3
Simply ask Copilot to perform LearnHouse operations:
> "List all courses in LearnHouse"
> "Create a new chapter called 'Introduction' in course 5"
> "Search for courses about Python"
---
API Reference
$3
`
http://localhost:3000/api/v1
`
$3
The client uses OAuth2 password flow:
`
POST /auth/login
Content-Type: application/x-www-form-urlencoded
username=admin@example.com&password=YourPassword
`
Returns:
`json
{
"user": { "id": 1, "email": "admin@example.com", ... },
"tokens": {
"access_token": "eyJ...",
"refresh_token": "eyJ..."
}
}
`
$3
| Method | Endpoint | Description |
| ------ | --------------------------------------------- | --------------- |
| GET | /courses/org_slug/{slug}/page/{p}/limit/{l} | List courses |
| GET | /courses/{uuid} | Get course |
| POST | /courses/ | Create course |
| PUT | /courses/{uuid} | Update course |
| DELETE | /courses/{uuid} | Delete course |
| GET | /chapters/{id} | Get chapter |
| POST | /chapters/ | Create chapter |
| PUT | /chapters/{id} | Update chapter |
| GET | /activities/{uuid} | Get activity |
| POST | /activities/ | Create activity |
| PUT | /activities/{uuid} | Update activity |
| GET | /search/org_slug/{slug}?query= | Search |
---
Testing Results
$3
| # | Tool | Status | Notes |
| --- | ------------------------ | ------------ | -------------------------------- |
| 1 | list_courses | β
Pass | 12 courses returned |
| 2 | get_course | β
Pass | Course details retrieved |
| 3 | create_course | β
Pass | Created course id=13 |
| 4 | update_course | β
Pass | Name updated |
| 5 | delete_course | β
Pass | Course deleted |
| 6 | list_chapters | β API Error | HTTP 500 (backend issue) |
| 7 | get_chapter | β
Pass | Chapter details retrieved |
| 8 | create_chapter | β
Pass | Created chapter id=62 |
| 9 | update_chapter | β
Pass | Name/description updated |
| 10 | list_activities | β
Pass | Activities listed |
| 11 | get_activity | β
Pass | Activity details retrieved |
| 12 | create_activity | β
Pass | Created activities (doc & video) |
| 13 | update_activity | β
Pass | Name updated |
| 14 | publish_activity | β
Pass | Activity published |
| 15 | set_document_content | β
Pass | TipTap content set |
| 16 | set_video_content | β
Pass | YouTube URL set |
| 17 | get_current_user | β
Pass | admin@example.com |
| 18 | get_organization | β
Pass | AgentOne org details |
| 19 | search | β
Pass | Found courses |
| 20 | get_course_progress | β API Error | Requires enrollment |
| 21 | mark_activity_complete | β API Error | Requires enrollment |
Result: 18/21 tools working (86% success rate)
The 3 failing tools have backend API issues, not MCP server bugs.
---
Troubleshooting
$3
`bash
Check Node.js version
node --version # Should be 18+
Reinstall dependencies
cd .mcp
rm -rf node_modules
pnpm install
`
$3
1. Verify credentials in environment variables
2. Check if user exists in LearnHouse
3. Ensure user has admin permissions
$3
- Verify the UUID/ID exists
- Check if the resource is in the correct organization
- Some endpoints require user enrollment (progress tools)
$3
`bash
Rebuild TypeScript
pnpm build
`
$3
1. Reload VS Code window
2. Check .vscode/mcp.json syntax
3. View Output β "MCP" channel for errors
---
Dependencies
| Package | Version | Purpose |
| ------------ | ------- | -------------------- |
| fastmcp | ^3.29.0 | MCP framework |
| zod | ^3.23.8 | Schema validation |
| typescript | ^5.x | Type safety |
| tsx | ^4.x | TypeScript execution |
---
License
MIT License - See LICENSE
---
Contributing
1. Fork the repository
2. Create a feature branch
3. Make changes to .mcp/src/
4. Test with pnpm inspect`