Skip to main content
Glama

pipeline_timeline

Retrieve and filter Azure DevOps pipeline run stages and jobs by state and result to analyze execution progress and outcomes.

Instructions

Retrieve the timeline of stages and jobs for a pipeline run, to reduce the amount of data returned, you can filter by state and result

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
projectIdNoThe ID or name of the project (Default: MyProject)
runIdYesRun identifier
timelineIdNoOptional timeline identifier to select a specific timeline record
pipelineIdNoOptional pipeline numeric ID for reference only
stateNoOptional state filter (single value or array) applied to returned timeline records
resultNoOptional result filter (single value or array) applied to returned timeline records

Implementation Reference

  • The core handler function `getPipelineTimeline` that fetches the pipeline timeline from Azure DevOps API, applies optional filters by state and result, and handles errors.
    export async function getPipelineTimeline( connection: WebApi, options: GetPipelineTimelineOptions, ): Promise<PipelineTimeline> { try { const buildApi = await connection.getBuildApi(); const projectId = options.projectId ?? defaultProject; const { runId, timelineId, state, result } = options; const route = `${encodeURIComponent(projectId)}/_apis/build/builds/${runId}/timeline`; const baseUrl = connection.serverUrl.replace(/\/+$/, ''); const url = new URL(`${route}`, `${baseUrl}/`); url.searchParams.set('api-version', API_VERSION); if (timelineId) { url.searchParams.set('timelineId', timelineId); } const requestOptions = buildApi.createRequestOptions( 'application/json', API_VERSION, ); const response = await buildApi.rest.get<PipelineTimeline | null>( url.toString(), requestOptions, ); if (response.statusCode === 404 || !response.result) { throw new AzureDevOpsResourceNotFoundError( `Timeline not found for run ${runId} in project ${projectId}`, ); } const timeline = response.result as PipelineTimeline & { records?: TimelineRecord[]; }; const stateFilters = normalizeFilter(state); const resultFilters = normalizeFilter(result); if (Array.isArray(timeline.records) && (stateFilters || resultFilters)) { const filteredRecords = timeline.records.filter((record) => { const recordState = stateToString(record.state); const recordResult = resultToString(record.result); const stateMatch = !stateFilters || (recordState && stateFilters.has(recordState)); const resultMatch = !resultFilters || (recordResult && resultFilters.has(recordResult)); return stateMatch && resultMatch; }); return { ...timeline, records: filteredRecords, } as PipelineTimeline; } return timeline; } catch (error) { if (error instanceof AzureDevOpsError) { throw error; } if (error instanceof Error) { const message = error.message.toLowerCase(); if ( message.includes('authentication') || message.includes('unauthorized') || message.includes('401') ) { throw new AzureDevOpsAuthenticationError( `Failed to authenticate: ${error.message}`, ); } if ( message.includes('not found') || message.includes('does not exist') || message.includes('404') ) { throw new AzureDevOpsResourceNotFoundError( `Pipeline timeline or project not found: ${error.message}`, ); } } throw new AzureDevOpsError( `Failed to retrieve pipeline timeline: ${ error instanceof Error ? error.message : String(error) }`, ); } }
  • Tool registration definition in the pipelinesTools array, specifying name, description, input schema, and MCP enabled flag.
    { name: 'pipeline_timeline', description: 'Retrieve the timeline of stages and jobs for a pipeline run, to reduce the amount of data returned, you can filter by state and result', inputSchema: zodToJsonSchema(GetPipelineTimelineSchema), mcp_enabled: true, },
  • Dispatcher case in handlePipelinesRequest that parses arguments, calls the handler, and formats the response for the pipeline_timeline tool.
    case 'pipeline_timeline': { const args = GetPipelineTimelineSchema.parse(request.params.arguments); const result = await getPipelineTimeline(connection, { ...args, projectId: args.projectId ?? defaultProject, }); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], }; }
  • Helper function to normalize filter values (state or result) into a Set for efficient matching.
    function normalizeFilter(value?: string | string[]): Set<string> | undefined { if (!value) { return undefined; } const values = Array.isArray(value) ? value : [value]; const normalized = values .map((item) => (typeof item === 'string' ? item.trim().toLowerCase() : '')) .filter((item) => item.length > 0); return normalized.length > 0 ? new Set(normalized) : undefined; }

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/Tiberriver256/mcp-server-azure-devops'

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