Skip to main content
Glama
jakedx6

Helios-9 MCP Server

by jakedx6

get_project_timeline

Retrieve project timeline with milestones and key events for a specific project ID, filtering by time range and completion status.

Instructions

Get project timeline with milestones and key events

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
project_idYesID of the project
include_completedNoWhether to include completed items
time_rangeNoTime range filterall

Implementation Reference

  • Main handler function for get_project_timeline tool. Parses input, fetches project, tasks, and documents, constructs timeline events, applies time filtering, identifies milestones, and returns structured timeline data.
    export const getProjectTimeline = requireAuth(async (args: any) => {
      const { project_id, include_completed, time_range } = GetProjectTimelineSchema.parse(args)
      
      logger.info('Getting project timeline', { project_id, time_range })
    
      const project = await supabaseService.getProject(project_id)
      if (!project) {
        throw new Error('Project not found')
      }
    
      // Get tasks and documents with dates
      const tasks = await supabaseService.getTasks({ project_id })
      const documents = await supabaseService.getDocuments({ project_id })
    
      // Create timeline events
      const timelineEvents = []
    
      // Add project creation
      timelineEvents.push({
        date: project.created_at,
        type: 'project_created',
        title: 'Project Created',
        description: `Project "${project.name}" was created`,
        metadata: { project_id }
      })
    
      // Add task events
      tasks.forEach(task => {
        if (task.created_at) {
          timelineEvents.push({
            date: task.created_at,
            type: 'task_created',
            title: `Task Created: ${task.title}`,
            description: task.description,
            metadata: { task_id: task.id, status: task.status }
          })
        }
    
        // started_at property doesn't exist in the database schema
    
        // completed_at property doesn't exist in the database schema
    
        if (task.due_date) {
          timelineEvents.push({
            date: task.due_date,
            type: 'task_due',
            title: `Task Due: ${task.title}`,
            description: task.status === 'done' ? 'Completed on time' : 'Due date',
            metadata: { task_id: task.id, is_overdue: new Date(task.due_date) < new Date() && task.status !== 'done' }
          })
        }
      })
    
      // Add document events
      documents.forEach(doc => {
        timelineEvents.push({
          date: doc.created_at,
          type: 'document_created',
          title: `Document Created: ${doc.title}`,
          metadata: { document_id: doc.id, document_type: doc.document_type }
        })
    
        if (doc.updated_at !== doc.created_at) {
          timelineEvents.push({
            date: doc.updated_at,
            type: 'document_updated',
            title: `Document Updated: ${doc.title}`,
            metadata: { document_id: doc.id }
          })
        }
      })
    
      // Filter by time range
      const filteredEvents = filterTimelineByRange(timelineEvents, time_range)
    
      // Sort by date
      filteredEvents.sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime())
    
      // Identify milestones (significant events)
      const milestones = identifyMilestones(filteredEvents, tasks)
    
      return {
        project: {
          id: project.id,
          name: project.name,
          status: project.status
        },
        timeline: filteredEvents,
        milestones,
        summary: {
          total_events: filteredEvents.length,
          tasks_created: filteredEvents.filter(e => e.type === 'task_created').length,
          tasks_completed: filteredEvents.filter(e => e.type === 'task_completed').length,
          documents_created: filteredEvents.filter(e => e.type === 'document_created').length,
          overdue_tasks: filteredEvents.filter(e => e.type === 'task_due' && e.metadata?.is_overdue).length
        }
      }
    })
  • Zod schema for validating input parameters: project_id (required), include_completed (boolean, default true), time_range (enum, default 'all').
    const GetProjectTimelineSchema = z.object({
      project_id: z.string().min(1),
      include_completed: z.boolean().default(true),
      time_range: z.enum(['all', 'past_month', 'next_month', 'current_quarter']).default('all')
    })
  • MCPTool registration object defining the tool name, description, and input schema for MCP protocol.
    export const getProjectTimelineTool: MCPTool = {
      name: 'get_project_timeline',
      description: 'Get project timeline with milestones and key events',
      inputSchema: {
        type: 'object',
        properties: {
          project_id: {
            type: 'string',
            description: 'ID of the project'
          },
          include_completed: {
            type: 'boolean',
            default: true,
            description: 'Whether to include completed items'
          },
          time_range: {
            type: 'string',
            enum: ['all', 'past_month', 'next_month', 'current_quarter'],
            default: 'all',
            description: 'Time range filter'
          }
        },
        required: ['project_id']
      }
    }
  • Object exporting all project handlers, including get_project_timeline mapped to its handler function for registration in the MCP server.
    export const projectHandlers = {
      list_projects: listProjects,
      get_project: getProject,
      create_project: createProject,
      update_project: updateProject,
      get_project_context: getProjectContext,
      archive_project: archiveProject,
      duplicate_project: duplicateProject,
      get_project_timeline: getProjectTimeline,
      bulk_update_projects: bulkUpdateProjects
  • Helper function to filter timeline events by specified time range (all, past_month, next_month, current_quarter). Used in the handler.
    function filterTimelineByRange(events: any[], timeRange: string): any[] {
      if (timeRange === 'all') return events
    
      const now = new Date()
      let startDate: Date
      let endDate: Date = now
    
      switch (timeRange) {
        case 'past_month':
          startDate = new Date(now.getFullYear(), now.getMonth() - 1, now.getDate())
          break
        case 'next_month':
          startDate = now
          endDate = new Date(now.getFullYear(), now.getMonth() + 1, now.getDate())
          break
        case 'current_quarter':
          const quarter = Math.floor(now.getMonth() / 3)
          startDate = new Date(now.getFullYear(), quarter * 3, 1)
          endDate = new Date(now.getFullYear(), quarter * 3 + 3, 0)
          break
        default:
          return events
      }
    
      return events.filter(event => {
        const eventDate = new Date(event.date)
        return eventDate >= startDate && eventDate <= endDate
      })
    }

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/jakedx6/helios9-MCP-Server'

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