Skip to main content
Glama

get_required_courses

Retrieve required courses with progress tracking for N Lobby school portal. Filter by grade, semester, or curriculum category to access detailed course information.

Instructions

Retrieve required courses information with detailed progress tracking

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
gradeNoFilter by grade level (1, 2, or 3) (optional)
semesterNoFilter by term year (e.g., "2024", "2025") (optional)
categoryNoFilter by curriculum category (e.g., "国語", "数学", "英語") (optional)

Implementation Reference

  • The primary handler for the 'get_required_courses' MCP tool. Parses input parameters, fetches raw courses data via this.api.getRequiredCourses(), applies filtering logic for grade/semester/category, computes aggregated statistics and groupings using helper methods, and formats a comprehensive summary response as JSON.
    case "get_required_courses":
      try {
        const { grade, semester, category } = args as {
          grade?: number;
          semester?: string;
          category?: string;
        };
    
        const courses = await this.api.getRequiredCourses();
    
        // Apply filters if provided
        let filteredCourses = courses;
    
        if (grade !== undefined) {
          // Filter by grade (year) - convert grade number to grade string
          const gradeString =
            grade === 1
              ? "1年次"
              : grade === 2
                ? "2年次"
                : grade === 3
                  ? "3年次"
                  : `${grade}年次`;
          filteredCourses = filteredCourses.filter(
            (course) => course.grade === gradeString,
          );
        }
    
        if (semester) {
          // Filter by semester/term - this data isn't directly available in the current structure
          // Could filter by term year or other available fields
          filteredCourses = filteredCourses.filter(
            (course) =>
              course.termYear &&
              course.termYear.toString().includes(semester),
          );
        }
    
        if (category) {
          // Filter by curriculum name (subject category)
          filteredCourses = filteredCourses.filter(
            (course) =>
              course.curriculumName &&
              course.curriculumName
                .toLowerCase()
                .includes(category.toLowerCase()),
          );
        }
    
        // Create a summary with useful information
        const summary = {
          totalCourses: filteredCourses.length,
          filters: { grade, semester, category },
          coursesByGrade: this.groupCoursesByGrade(filteredCourses),
          coursesByCurriculum:
            this.groupCoursesByCurriculum(filteredCourses),
          completedCourses: filteredCourses.filter(
            (course) => course.isCompleted,
          ).length,
          inProgressCourses: filteredCourses.filter(
            (course) => course.isInProgress,
          ).length,
          courses: filteredCourses,
        };
    
        return {
          content: [
            {
              type: "text",
              text: JSON.stringify(summary, null, 2),
            },
          ],
        };
      } catch (error) {
        return {
          content: [
            {
              type: "text",
              text: `Error: ${error instanceof Error ? error.message : "Unknown error"}\n\nTo authenticate:\n1. Login to N Lobby in your browser\n2. Open Developer Tools (F12)\n3. Go to Application/Storage tab\n4. Copy cookies and use the set_cookies tool\n5. Use health_check to verify connection`,
            },
          ],
        };
      }
  • Input schema definition for the get_required_courses tool, specifying optional filtering parameters: grade (number), semester (string), category (string). Used in tool registration response.
    {
      name: "get_required_courses",
      description:
        "Retrieve required courses information with detailed progress tracking",
      inputSchema: {
        type: "object",
        properties: {
          grade: {
            type: "number",
            description: "Filter by grade level (1, 2, or 3) (optional)",
          },
          semester: {
            type: "string",
            description:
              'Filter by term year (e.g., "2024", "2025") (optional)',
          },
          category: {
            type: "string",
            description:
              'Filter by curriculum category (e.g., "国語", "数学", "英語") (optional)',
          },
        },
      },
    },
  • src/server.ts:154-450 (registration)
    Registration of all available tools including 'get_required_courses' via the ListToolsRequestSchema handler. The static tools array defines capabilities and is returned to MCP clients.
    this.server.setRequestHandler(ListToolsRequestSchema, async () => {
      return {
        tools: [
          {
            name: "get_news",
            description: "Retrieve school news",
            inputSchema: {
              type: "object",
              properties: {
                category: {
                  type: "string",
                  description: "Filter by category (optional)",
                },
                limit: {
                  type: "number",
                  description:
                    "Maximum number of news items to retrieve (optional, default: 10)",
                  minimum: 1,
                  default: 10,
                },
                sort: {
                  type: "string",
                  description:
                    "Sort order: 'newest' (default), 'oldest', 'title-asc', 'title-desc'",
                  enum: ["newest", "oldest", "title-asc", "title-desc"],
                },
              },
            },
          },
          {
            name: "get_news_detail",
            description:
              "Retrieve detailed information for a specific news article",
            inputSchema: {
              type: "object",
              properties: {
                newsId: {
                  type: "string",
                  description: "The ID of the news article to retrieve",
                },
                markAsRead: {
                  type: "boolean",
                  description:
                    "Mark the news article as read (optional, default: false)",
                  default: false,
                },
              },
              required: ["newsId"],
            },
          },
          {
            name: "get_account_info",
            description:
              "Extract account information by parsing Next.js flight data from a rendered page",
            inputSchema: {
              type: "object",
              properties: {},
            },
          },
          {
            name: "get_student_card_screenshot",
            description:
              "Capture a screenshot of the student ID card by following the secure portal redirect flow",
            inputSchema: {
              type: "object",
              properties: {},
            },
          },
          {
            name: "get_required_courses",
            description:
              "Retrieve required courses information with detailed progress tracking",
            inputSchema: {
              type: "object",
              properties: {
                grade: {
                  type: "number",
                  description: "Filter by grade level (1, 2, or 3) (optional)",
                },
                semester: {
                  type: "string",
                  description:
                    'Filter by term year (e.g., "2024", "2025") (optional)',
                },
                category: {
                  type: "string",
                  description:
                    'Filter by curriculum category (e.g., "国語", "数学", "英語") (optional)',
                },
              },
            },
          },
          {
            name: "get_schedule",
            description:
              "Get school schedule for a specific date (backward compatibility)",
            inputSchema: {
              type: "object",
              properties: {
                date: {
                  type: "string",
                  description:
                    "Date in YYYY-MM-DD format (optional, defaults to today)",
                },
              },
            },
          },
          {
            name: "get_calendar_events",
            description: "Get calendar events with advanced options",
            inputSchema: {
              type: "object",
              properties: {
                calendar_type: {
                  type: "string",
                  enum: ["personal", "school"],
                  description:
                    "Type of calendar to retrieve (personal or school)",
                  default: "personal",
                },
                from_date: {
                  type: "string",
                  description:
                    "Start date in YYYY-MM-DD format (optional). If only from_date is provided, it will be treated as a single day.",
                },
                to_date: {
                  type: "string",
                  description:
                    "End date in YYYY-MM-DD format (optional). Must be at least 1 day after from_date when both are provided.",
                },
                period: {
                  type: "string",
                  enum: ["today", "week", "month"],
                  description:
                    'Predefined period (optional, overrides from/to dates). Use "today" for single day queries.',
                },
              },
            },
          },
          {
            name: "test_calendar_endpoints",
            description: "Test both personal and school calendar endpoints",
            inputSchema: {
              type: "object",
              properties: {
                from_date: {
                  type: "string",
                  description:
                    "Start date in YYYY-MM-DD format (optional). If only from_date is provided, it will be treated as a single day.",
                },
                to_date: {
                  type: "string",
                  description:
                    "End date in YYYY-MM-DD format (optional). Must be at least 1 day after from_date when both are provided.",
                },
              },
            },
          },
    
          {
            name: "set_cookies",
            description: "Set authentication cookies for N Lobby access",
            inputSchema: {
              type: "object",
              properties: {
                cookies: {
                  type: "string",
                  description:
                    "Cookie string from authenticated N Lobby session",
                },
              },
              required: ["cookies"],
            },
          },
          {
            name: "check_cookies",
            description: "Check if authentication cookies are set",
            inputSchema: {
              type: "object",
              properties: {},
            },
          },
          {
            name: "health_check",
            description: "Check if N Lobby API connection is working",
            inputSchema: {
              type: "object",
              properties: {},
            },
          },
    
          {
            name: "debug_connection",
            description: "Debug N Lobby connection with detailed information",
            inputSchema: {
              type: "object",
              properties: {
                endpoint: {
                  type: "string",
                  description: "Endpoint to test (default: /news)",
                  default: "/news",
                },
              },
            },
          },
    
          {
            name: "test_page_content",
            description: "Test page content retrieval and show sample content",
            inputSchema: {
              type: "object",
              properties: {
                endpoint: {
                  type: "string",
                  description: "Endpoint to test (default: /news)",
                  default: "/news",
                },
                length: {
                  type: "number",
                  description: "Number of characters to show (default: 1000)",
                  default: 1000,
                },
              },
            },
          },
    
          {
            name: "test_trpc_endpoint",
            description: "Test specific tRPC endpoint with detailed response",
            inputSchema: {
              type: "object",
              properties: {
                method: {
                  type: "string",
                  description:
                    "tRPC method to test (e.g., news.getUnreadNewsCount, user.updateLastAccess)",
                  default: "user.updateLastAccess",
                },
                params: {
                  type: "string",
                  description: "JSON string of parameters (optional)",
                },
              },
            },
          },
          {
            name: "verify_authentication",
            description:
              "Verify authentication status and cookie synchronization across all clients",
            inputSchema: {
              type: "object",
              properties: {},
            },
          },
    
          {
            name: "interactive_login",
            description:
              "Open browser for manual login to N Lobby (no credentials required)",
            inputSchema: {
              type: "object",
              properties: {},
            },
          },
          {
            name: "login_help",
            description: "Get help and troubleshooting tips for N Lobby login",
            inputSchema: {
              type: "object",
              properties: {
                email: {
                  type: "string",
                  description:
                    "Your email address (optional, for personalized help)",
                },
              },
            },
          },
          {
            name: "mark_news_as_read",
            description: "Mark news articles as read",
            inputSchema: {
              type: "object",
              properties: {
                ids: {
                  type: "array",
                  items: {
                    type: "string",
                  },
                  description: "Array of news article IDs to mark as read",
                },
              },
              required: ["ids"],
            },
          },
        ],
      };
  • Helper utility functions groupCoursesByGrade and groupCoursesByCurriculum used exclusively by the get_required_courses handler to create summary aggregations of filtered courses by grade level and curriculum/subject.
    private groupCoursesByGrade(courses: Course[]): Record<string, number> {
      const groups: Record<string, number> = {};
    
      for (const course of courses) {
        const grade = course.grade || "Unknown";
        groups[grade] = (groups[grade] || 0) + 1;
      }
    
      return groups;
    }
    
    private groupCoursesByCurriculum(courses: Course[]): Record<string, number> {
      const groups: Record<string, number> = {};
    
      for (const course of courses) {
        const curriculum = course.curriculumName || "Unknown";
        groups[curriculum] = (groups[curriculum] || 0) + 1;
      }
    
      return groups;
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden for behavioral disclosure. While 'Retrieve' implies a read-only operation, it doesn't specify authentication requirements, rate limits, pagination behavior, error conditions, or what 'detailed progress tracking' actually entails in the response.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that gets straight to the point with zero wasted words. It's appropriately sized for a retrieval tool with three optional parameters.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only tool with full schema coverage but no output schema, the description is minimally adequate. It states what the tool does but lacks important context about authentication needs, response format, and how it differs from similar educational tools in the sibling set.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds no parameter-specific information beyond what's already in the schema (which has 100% coverage). It mentions 'detailed progress tracking' which might relate to the return data, but doesn't explain how the three optional parameters interact or affect the results.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with a specific verb ('Retrieve') and resource ('required courses information'), and adds meaningful context about 'detailed progress tracking'. It doesn't explicitly differentiate from sibling tools, but since none of the siblings appear to retrieve course information, this is sufficiently clear.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention prerequisites, timing considerations, or how it relates to sibling tools like 'get_schedule' or 'get_account_info' that might also provide educational information.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

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/minagishl/nlobby-cli'

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