Skip to main content
Glama

Reddit MCP Server

by ozipi
track-handlers.ts7.05 kB
/** * @file BrainTrack tool handlers * @module handlers/tools/track-handlers * * @remarks * These handlers implement track (learning path) management where users can: * - Create tracks (collections of courses) * - View their tracks * - Add courses to tracks * - Enroll in tracks */ import { logger } from '../../utils/logger.js'; import type { BrainloopService, Track, TrackCourse } from '../../services/brainloop/brainloop-service.js'; import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; interface BrainloopToolContext { brainloopService: BrainloopService; userId: string; sessionId: string; } /** * Create a new BrainTrack (collection of courses) */ export async function handleCreateTrack( args: { title: string; description: string; icon?: string; hero?: string; isPrivate?: boolean; slug?: string; }, context: BrainloopToolContext ): Promise<CallToolResult> { try { logger.info(`🎯 Creating track: "${args.title}" for user ${context.userId}`); const track = await context.brainloopService.createTrack({ title: args.title, description: args.description, icon: args.icon, hero: args.hero, isPrivate: args.isPrivate ?? true, slug: args.slug, }); logger.info(`✅ Track created with ID: ${track.id}`); return { content: [{ type: 'text', text: `🎉 **Track Created Successfully!**\n\n` + `**${track.title}**\n` + `${track.description}\n\n` + `**Track ID:** ${track.id}\n` + `**Slug:** ${track.slug}\n` + `**Visibility:** ${track.isPrivate ? '🔒 Private' : '🌍 Public'}\n` + (track.icon ? `**Icon:** ${track.icon}\n` : '') + `\n💡 **Next steps:** Add courses to this track using \`add_course_to_track\`.` }] }; } catch (error) { logger.error('Failed to create track', { error, title: args.title }); throw new Error(`Failed to create track: ${error instanceof Error ? error.message : String(error)}`); } } /** * View all user's tracks */ export async function handleViewTracks( _args: any, context: BrainloopToolContext ): Promise<CallToolResult> { try { logger.info(`📚 Viewing tracks for user ${context.userId}`); const tracks = await context.brainloopService.getTracks(); return { content: [{ type: 'text', text: `🎯 **Your BrainTracks** (${tracks.length} total)\n\n` + (tracks.length === 0 ? `No tracks yet. Create one with \`create_track\`!` : tracks.map((track: Track) => `${track.icon || '🎯'} **${track.title}**\n` + ` 📝 ${track.description}\n` + ` 🆔 ID: ${track.id}\n` + ` 📚 Courses: ${track._count?.trackCourses || 0}\n` + ` 👥 Learners: ${track._count?.enrollments || 0}\n` + ` ${track.isPrivate ? '🔒 Private' : '🌍 Public'}${track.isOwner ? ' • 👑 Owner' : ''}${track.isEnrolled ? ' • ✅ Enrolled' : ''}\n` ).join('\n')) }] }; } catch (error) { logger.error('Failed to view tracks', { error }); throw new Error(`Failed to view tracks: ${error instanceof Error ? error.message : String(error)}`); } } /** * Get detailed information about a track */ export async function handleGetTrack( args: { trackId: string }, context: BrainloopToolContext ): Promise<CallToolResult> { try { logger.info(`🔍 Getting track ${args.trackId} for user ${context.userId}`); const track = await context.brainloopService.getTrack(args.trackId); let responseText = `${track.icon || '🎯'} **${track.title}**\n\n`; responseText += `📝 ${track.description}\n\n`; responseText += `**Track Details:**\n`; responseText += ` 🆔 ID: ${track.id}\n`; responseText += ` 🔗 Slug: ${track.slug}\n`; responseText += ` ${track.isPrivate ? '🔒 Private' : '🌍 Public'}\n`; responseText += ` 👤 Created by: ${track.user.name || track.user.email}\n`; responseText += ` 👥 Learners: ${track._count?.enrollments || 0}\n`; responseText += ` ${track.isOwner ? '👑 You own this track\n' : ''}`; responseText += ` ${track.isEnrolled ? '✅ You are enrolled\n' : ''}\n`; if (track.trackCourses && track.trackCourses.length > 0) { responseText += `**Learning Path (${track.trackCourses.length} courses):**\n\n`; track.trackCourses.forEach((tc: TrackCourse, index: number) => { responseText += `${index + 1}. 📚 **${tc.course.title}**\n`; responseText += ` ${tc.course.description}\n`; responseText += ` Course ID: ${tc.course.id}\n\n`; }); } else { responseText += `**No courses yet.** Add courses using \`add_course_to_track\`.`; } return { content: [{ type: 'text', text: responseText }] }; } catch (error) { logger.error('Failed to get track', { error, trackId: args.trackId }); throw new Error(`Failed to get track: ${error instanceof Error ? error.message : String(error)}`); } } /** * Add a course to a track */ export async function handleAddCourseToTrack( args: { trackId: string; courseId: string }, context: BrainloopToolContext ): Promise<CallToolResult> { try { logger.info(`➕ Adding course ${args.courseId} to track ${args.trackId}`); const result = await context.brainloopService.addCourseToTrack(args.trackId, args.courseId); return { content: [{ type: 'text', text: `✅ **Course Added to Track!**\n\n` + `**Course:** ${result.trackCourse.course.title}\n` + `**Track:** ${result.track.title}\n` + `**Position:** #${result.trackCourse.order}\n\n` + `This course is now part of the learning path!` }] }; } catch (error) { logger.error('Failed to add course to track', { error, trackId: args.trackId, courseId: args.courseId }); throw new Error(`Failed to add course to track: ${error instanceof Error ? error.message : String(error)}`); } } /** * Enroll in a track */ export async function handleEnrollInTrack( args: { trackId: string }, context: BrainloopToolContext ): Promise<CallToolResult> { try { logger.info(`📝 Enrolling user ${context.userId} in track ${args.trackId}`); const result = await context.brainloopService.enrollInTrack(args.trackId); return { content: [{ type: 'text', text: `🎉 **Successfully Enrolled in Track!**\n\n` + `**Track:** ${result.track.title}\n` + `**Courses:** ${result.track._count?.trackCourses || 0}\n\n` + `✅ You are now enrolled in all ${result.track._count?.trackCourses || 0} courses in this track!\n\n` + result.message }] }; } catch (error) { logger.error('Failed to enroll in track', { error, trackId: args.trackId }); throw new Error(`Failed to enroll in track: ${error instanceof Error ? error.message : String(error)}`); } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ozipi/brainloop-mcp-server-v2'

If you have feedback or need assistance with the MCP directory API, please join our Discord server