Skip to main content
Glama

update_planned_course

Idempotent

Update details of a planned course including dates, costs, participant limits, and teacher assignments.

Instructions

Update a planned course.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
idYesID of the planned course to update
is_publishedNoBoolean if is published on the website.
course_idNoUnique identifier of the course.
start_dateNoDate at which the planned course starts. Only needed for fixed planned courses.
end_dateNoDate at which the planned course ends. Only needed for fixed planned courses.
min_participantsNoA number representing the minimum number of participants that can enroll for the planned course.
max_participantsNoA number representing the maximum number of participants that can enroll for the planned course.
cost_schemeNoThe cost schema that the payment will follow for the specified course.
costNoA positive float representing the price of the planned course.
course_variant_idNoUnique identifier of the course variant.
course_location_idNoUnique identifier of the course location.
durationNoThe period of time of the planned course. Only needed for flexible planned courses.
teacher_idsNoThe ids of the teachers in the course
customNo
custom_associationsNo

Implementation Reference

  • The handler for 'update_planned_course' - an async function that destructures id from the input, makes an apiPatch call to /planned_courses/{id}, logs the response, and returns the formatted update.
    async ({ id, ...body }) => {
      try {
        const record = await apiPatch<EduframeRecord>(`/planned_courses/${id}`, body);
        void logResponse("update_planned_course", { id, ...body }, record);
        return formatUpdate(record, "planned course");
      } catch (error) {
        return formatError(error);
      }
    },
  • Input schema for 'update_planned_course' defining all optional/required fields: id (required), is_published, course_id, start_date, end_date, min_participants, max_participants, cost_scheme, cost, course_variant_id, course_location_id, duration, teacher_ids, custom, custom_associations.
    inputSchema: {
      id: z.number().int().positive().describe("ID of the planned course to update"),
      is_published: z.boolean().optional().describe("Boolean if is published on the website."),
      course_id: z.number().int().optional().describe("Unique identifier of the course."),
      start_date: z
        .string()
        .optional()
        .describe("Date at which the planned course starts. Only needed for fixed planned courses."),
      end_date: z
        .string()
        .optional()
        .describe("Date at which the planned course ends. Only needed for fixed planned courses."),
      min_participants: z
        .number()
        .int()
        .optional()
        .describe("A number representing the minimum number of participants that can enroll for the planned course."),
      max_participants: z
        .number()
        .int()
        .optional()
        .describe("A number representing the maximum number of participants that can enroll for the planned course."),
      cost_scheme: plannedCourseCostSchemeEnum
        .optional()
        .describe("The cost schema that the payment will follow for the specified course."),
      cost: z.number().optional().describe("A positive float representing the price of the planned course."),
      course_variant_id: z.number().int().optional().describe("Unique identifier of the course variant."),
      course_location_id: z.number().int().optional().describe("Unique identifier of the course location."),
      duration: z
        .number()
        .optional()
        .describe("The period of time of the planned course. Only needed for flexible planned courses."),
      teacher_ids: z.array(z.string()).optional().describe("The ids of the teachers in the course"),
      custom: z.record(z.unknown()).optional(),
      custom_associations: z.record(z.unknown()).optional(),
    },
  • Registration of 'update_planned_course' tool via server.registerTool() with description, annotations (readOnlyHint: false, destructiveHint: false, idempotentHint: true), and inputSchema.
    server.registerTool(
      "update_planned_course",
      {
        description: "Update a planned course.",
        annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },
        inputSchema: {
          id: z.number().int().positive().describe("ID of the planned course to update"),
          is_published: z.boolean().optional().describe("Boolean if is published on the website."),
          course_id: z.number().int().optional().describe("Unique identifier of the course."),
          start_date: z
            .string()
            .optional()
            .describe("Date at which the planned course starts. Only needed for fixed planned courses."),
          end_date: z
            .string()
            .optional()
            .describe("Date at which the planned course ends. Only needed for fixed planned courses."),
          min_participants: z
            .number()
            .int()
            .optional()
            .describe("A number representing the minimum number of participants that can enroll for the planned course."),
          max_participants: z
            .number()
            .int()
            .optional()
            .describe("A number representing the maximum number of participants that can enroll for the planned course."),
          cost_scheme: plannedCourseCostSchemeEnum
            .optional()
            .describe("The cost schema that the payment will follow for the specified course."),
          cost: z.number().optional().describe("A positive float representing the price of the planned course."),
          course_variant_id: z.number().int().optional().describe("Unique identifier of the course variant."),
          course_location_id: z.number().int().optional().describe("Unique identifier of the course location."),
          duration: z
            .number()
            .optional()
            .describe("The period of time of the planned course. Only needed for flexible planned courses."),
          teacher_ids: z.array(z.string()).optional().describe("The ids of the teachers in the course"),
          custom: z.record(z.unknown()).optional(),
          custom_associations: z.record(z.unknown()).optional(),
        },
      },
      async ({ id, ...body }) => {
        try {
          const record = await apiPatch<EduframeRecord>(`/planned_courses/${id}`, body);
          void logResponse("update_planned_course", { id, ...body }, record);
          return formatUpdate(record, "planned course");
        } catch (error) {
          return formatError(error);
        }
      },
    );
  • Enum definitions used in the schema: plannedCourseCostSchemeEnum (zod enum: 'student' | 'order' | 'tbd' | 'free').
    const plannedCourseTypeEnum = z.enum(["FixedPlannedCourse", "FlexiblePlannedCourse"]);
    const plannedCourseCostSchemeEnum = z.enum(["student", "order", "tbd", "free"]);
  • Import and registration of registerPlannedCourseTools in the central tools index.
    import { registerPlannedCourseTools } from "./planned_courses";
    import { registerPlanningAttendeeTools } from "./planning_attendees";
    import { registerPlanningConflictTools } from "./planning_conflicts";
    import { registerPlanningEventTools } from "./planning_events";
    import { registerPlanningLocationTools } from "./planning_locations";
    import { registerPlanningMaterialTools } from "./planning_materials";
    import { registerPlanningRequiredTeacherGroupAttendeeTools } from "./planning_required_teacher_group_attendees";
    import { registerPlanningTeacherTools } from "./planning_teachers";
    import { registerProgramEditionTools } from "./program_editions";
    import { registerProgramElementTools } from "./program_elements";
    import { registerProgramEnrollmentTools } from "./program_enrollments";
    import { registerProgramPersonalProgramElementTools } from "./program_personal_program_elements";
    import { registerProgramProgramTools } from "./program_programs";
    import { registerReferralTools } from "./referrals";
    import { registerSignupQuestionTools } from "./signup_questions";
    import { registerTaskTools } from "./tasks";
    import { registerTeacherEnrollmentTools } from "./teacher_enrollments";
    import { registerTeacherRoleTools } from "./teacher_roles";
    import { registerTeacherTools } from "./teachers";
    import { registerTheseTools } from "./theses";
    import { registerUserTools } from "./users";
    import { registerWebhookNotificationTools } from "./webhook_notifications";
    import { registerWebhookTools } from "./webhooks";
    
    const tools: Array<(server: McpServer) => void> = [
      registerAccountTools,
      registerAffiliationTools,
      registerAttendanceTools,
      registerAuthenticationTools,
      registerCatalogProductTools,
      registerCatalogVariantTools,
      registerCategorieTools,
      registerCertificateTools,
      registerCommentTools,
      registerCourseLocationTools,
      registerCourseTabTools,
      registerCourseVariantTools,
      registerCourseTools,
      registerCreditCategorieTools,
      registerCreditTools,
      registerCustomAssociationTools,
      registerCustomFieldOptionTools,
      registerCustomObjectTools,
      registerCustomRecordTools,
      registerDiscountCodeTools,
      registerEditionDescriptionSectionTools,
      registerEducatorTools,
      registerEmailTools,
      registerEnrollmentTools,
      registerGradeTools,
      registerInvoiceVatTools,
      registerInvoiceTools,
      registerLabelTools,
      registerLeadTools,
      registerMaterialGroupTools,
      registerMaterialTools,
      registerMeetingLocationTools,
      registerMeetingTools,
      registerOrderTools,
      registerOrganizationTools,
      registerPaymentMethodTools,
      registerPaymentOptionTools,
      registerPaymentTools,
      registerPlannedCourseTools,
Behavior2/5

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

Annotations indicate this is idempotent and non-destructive, but the description adds no behavioral context beyond the name. It does not explain partial update behavior, required fields beyond 'id', or what happens to existing data when updating.

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

Conciseness3/5

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

The description is a single sentence, which is concise but overly terse given the tool's complexity (15 parameters, nested objects). It lacks structure and important details like what fields can be updated.

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

Completeness1/5

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

Given the high parameter count, nested objects, and lack of output schema, the description is completely inadequate. It fails to explain return values, behavior on error, or any context beyond the tool's name.

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 input schema covers 87% of parameters with descriptions, so the schema does the heavy lifting. The description adds no additional parameter meaning, earning the baseline score of 3.

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

Purpose3/5

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

The description 'Update a planned course' is a clear verb+resource pair, but it does not distinguish this tool from siblings like create_planned_course or cancel_planned_course. It is essentially a tautology of the tool name.

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?

No guidance is provided on when to use this tool versus alternatives. There is no mention of prerequisites, common use cases, or conditions that would help an agent decide between this and other update tools.

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/martijnpieters/eduframe-mcp'

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