Skip to main content
Glama
phase-schema.ts5.48 kB
import { z } from 'zod'; const tagSchema = z.object({ key: z.string(), value: z.string(), }); const milestoneSchema = z.object({ id: z.string(), title: z.string(), completed: z.boolean(), completedAt: z.string().optional(), }); const blockerSchema = z.object({ description: z.string(), reportedAt: z.string(), resolvedAt: z.string().optional(), }); const prioritySchema = z.enum(['critical', 'high', 'medium', 'low']); const phaseStatusSchema = z.enum(['planned', 'in_progress', 'completed', 'blocked', 'skipped']); const effortUnitSchema = z.enum(['minutes', 'hours', 'days', 'weeks', 'story-points']); const confidenceSchema = z.enum(['low', 'medium', 'high']); const estimatedEffortSchema = z.object({ value: z.number(), unit: effortUnitSchema, confidence: confidenceSchema, }); const phaseDataSchema = z.object({ title: z.string().optional(), description: z.string().optional(), parentId: z.string().optional(), order: z.number().optional(), // Explicit order for phase positioning objectives: z.array(z.string()).optional(), deliverables: z.array(z.string()).optional(), successCriteria: z.array(z.string()).optional(), estimatedEffort: estimatedEffortSchema.optional(), implementationNotes: z.string().optional(), priority: prioritySchema.optional(), // Schedule dates (kept flat to match current pattern) startDate: z.string().optional(), endDate: z.string().optional(), dueDate: z.string().optional(), // Progress tracking milestones: z.array(milestoneSchema).optional(), blockers: z.array(blockerSchema).optional(), tags: z.array(tagSchema).optional(), }); const phaseUpdatesSchema = z.object({ title: z.string().optional(), description: z.string().optional(), objectives: z.array(z.string()).optional(), deliverables: z.array(z.string()).optional(), successCriteria: z.array(z.string()).optional(), status: phaseStatusSchema.optional(), blockingReason: z.string().optional(), progress: z.number().min(0).max(100).optional(), implementationNotes: z.string().optional(), priority: prioritySchema.optional(), }); // Base schema with all fields const basePhaseSchema = z.object({ action: z.enum(['add', 'get', 'get_many', 'get_tree', 'update', 'update_status', 'move', 'delete', 'get_next_actions', 'complete_and_advance', 'get_history', 'diff', 'list_fields']), planId: z.string(), phaseId: z.string().optional(), phaseIds: z.array(z.string()).optional(), phase: phaseDataSchema.optional(), updates: phaseUpdatesSchema.optional(), status: phaseStatusSchema.optional(), progress: z.number().min(0).max(100).optional(), notes: z.string().optional(), actualEffort: z.number().optional(), newParentId: z.string().optional(), newOrder: z.number().optional(), deleteChildren: z.boolean().optional(), includeCompleted: z.boolean().optional(), maxDepth: z.number().optional(), fields: z.array(z.string()).optional(), excludeMetadata: z.boolean().optional(), excludeComputed: z.boolean().optional(), limit: z.number().optional(), // For diff action version1: z.number().optional(), version2: z.number().optional(), }); // Type for the base schema type PhaseInput = z.infer<typeof basePhaseSchema>; // Schema with superRefine for required field validation based on action export const phaseSchema = basePhaseSchema.superRefine((data: PhaseInput, ctx) => { switch (data.action) { case 'add': // phase and phase.title are required if (data.phase === undefined) { ctx.addIssue({ code: 'custom', message: 'phase object is required for add action', path: ['phase'], }); return; } if (typeof data.phase.title !== 'string' || data.phase.title === '') { ctx.addIssue({ code: 'custom', message: 'phase.title is required for add action', path: ['phase', 'title'], }); } break; case 'get': case 'update': case 'update_status': case 'move': case 'delete': case 'complete_and_advance': case 'get_history': case 'diff': // phaseId is required if (typeof data.phaseId !== 'string' || data.phaseId === '') { ctx.addIssue({ code: 'custom', message: `phaseId is required for ${data.action} action`, path: ['phaseId'], }); } break; case 'get_many': // phaseIds is required if (!Array.isArray(data.phaseIds) || data.phaseIds.length === 0) { ctx.addIssue({ code: 'custom', message: 'phaseIds is required for get_many action', path: ['phaseIds'], }); } break; case 'get_tree': case 'get_next_actions': case 'list_fields': // Only planId is required (already validated by base schema) break; } }); export const phaseToolDescription = 'Manage implementation phases/tasks in hierarchical structure. Break selected solutions into phases with objectives, deliverables, and estimates. Track progress, update status (planned/in_progress/completed/blocked), and get next actionable items. For plan overview/summary, use get_tree with fields parameter to get compact tree. Use link tool with depends_on relation to create phase dependencies with cycle detection. Use after solution selection. Actions: add, get, get_many, get_tree, update, update_status, move, delete, get_next_actions, complete_and_advance, get_history, diff.';

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/cppmyjob/cpp-mcp-planner'

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