UNPKG

@tiberriver256/mcp-server-azure-devops

Version:

Azure DevOps reference server for the Model Context Protocol (MCP)

91 lines 4.23 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.manageWorkItemLink = manageWorkItemLink; const WorkItemTrackingInterfaces_1 = require("azure-devops-node-api/interfaces/WorkItemTrackingInterfaces"); const errors_1 = require("../../../shared/errors"); /** * Manage (add, remove, or update) a link between two work items * * @param connection The Azure DevOps WebApi connection * @param projectId The ID or name of the project * @param options Options for managing the work item link * @returns The updated source work item * @throws {AzureDevOpsResourceNotFoundError} If either work item is not found */ async function manageWorkItemLink(connection, projectId, options) { try { const { sourceWorkItemId, targetWorkItemId, operation, relationType, newRelationType, comment, } = options; // Input validation if (!sourceWorkItemId) { throw new Error('Source work item ID is required'); } if (!targetWorkItemId) { throw new Error('Target work item ID is required'); } if (!relationType) { throw new Error('Relation type is required'); } if (operation === 'update' && !newRelationType) { throw new Error('New relation type is required for update operation'); } const witApi = await connection.getWorkItemTrackingApi(); // Create the JSON patch document const document = []; // Construct the relationship URL const relationshipUrl = `${connection.serverUrl}/_apis/wit/workItems/${targetWorkItemId}`; let relationIndex = -1; if (operation === 'remove' || operation === 'update') { const sourceWorkItem = await witApi.getWorkItem(sourceWorkItemId, undefined, undefined, WorkItemTrackingInterfaces_1.WorkItemExpand.Relations); if (!sourceWorkItem) { throw new errors_1.AzureDevOpsResourceNotFoundError(`Work item '${sourceWorkItemId}' not found`); } const relations = sourceWorkItem.relations || []; const targetSuffix = `/_apis/wit/workItems/${targetWorkItemId}`.toLowerCase(); relationIndex = relations.findIndex((rel) => rel.rel?.toLowerCase() === relationType.toLowerCase() && rel.url?.toLowerCase().endsWith(targetSuffix)); if (relationIndex === -1) { throw new errors_1.AzureDevOpsResourceNotFoundError(`Relation of type '${relationType}' to target work item '${targetWorkItemId}' not found on source work item '${sourceWorkItemId}'`); } } if (operation === 'add' || operation === 'update') { // For 'update', we'll first remove the old link, then add the new one if (operation === 'update') { document.push({ op: 'remove', path: `/relations/${relationIndex}`, }); } // Add the new relationship document.push({ op: 'add', path: '/relations/-', value: { rel: operation === 'update' ? newRelationType : relationType, url: relationshipUrl, ...(comment ? { attributes: { comment } } : {}), }, }); } else if (operation === 'remove') { // Remove the relationship document.push({ op: 'remove', path: `/relations/${relationIndex}`, }); } // Update the work item with the new relationship const updatedWorkItem = await witApi.updateWorkItem({}, // customHeaders document, sourceWorkItemId, projectId); if (!updatedWorkItem) { throw new errors_1.AzureDevOpsResourceNotFoundError(`Work item '${sourceWorkItemId}' not found`); } return updatedWorkItem; } catch (error) { if (error instanceof errors_1.AzureDevOpsError) { throw error; } throw new Error(`Failed to manage work item link: ${error instanceof Error ? error.message : String(error)}`); } } //# sourceMappingURL=feature.js.map