@tiberriver256/mcp-server-azure-devops
Version:
Azure DevOps reference server for the Model Context Protocol (MCP)
155 lines • 6.11 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateWorkItem = updateWorkItem;
const WorkItemTrackingInterfaces_1 = require("azure-devops-node-api/interfaces/WorkItemTrackingInterfaces");
const errors_1 = require("../../../shared/errors");
/**
* Update a work item
*
* @param connection The Azure DevOps WebApi connection
* @param workItemId The ID of the work item to update
* @param options Options for updating the work item
* @returns The updated work item
* @throws {AzureDevOpsResourceNotFoundError} If the work item is not found
*/
async function updateWorkItem(connection, workItemId, options) {
try {
const witApi = await connection.getWorkItemTrackingApi();
// Create the JSON patch document
const document = [];
// Add optional fields if provided
if (options.title) {
document.push({
op: 'add',
path: '/fields/System.Title',
value: options.title,
});
}
if (options.description) {
document.push({
op: 'add',
path: '/fields/System.Description',
value: options.description,
});
}
if (options.assignedTo) {
document.push({
op: 'add',
path: '/fields/System.AssignedTo',
value: options.assignedTo,
});
}
if (options.areaPath) {
document.push({
op: 'add',
path: '/fields/System.AreaPath',
value: options.areaPath,
});
}
if (options.iterationPath) {
document.push({
op: 'add',
path: '/fields/System.IterationPath',
value: options.iterationPath,
});
}
if (options.priority) {
document.push({
op: 'add',
path: '/fields/Microsoft.VSTS.Common.Priority',
value: options.priority,
});
}
if (options.state) {
document.push({
op: 'add',
path: '/fields/System.State',
value: options.state,
});
}
// Add tags logic
// Azure DevOps treats op:'add' on System.Tags as additive (merge) rather
// than a full replacement. Use op:'replace' to truly overwrite when the
// field already has a value; fall back to op:'add' when it is empty
// (JSON-Patch 'replace' fails on a missing/empty field).
if (options.tags !== undefined) {
const currentWorkItem = await witApi.getWorkItem(workItemId, [
'System.Tags',
]);
if (!currentWorkItem) {
throw new errors_1.AzureDevOpsResourceNotFoundError(`Work item '${workItemId}' not found`);
}
const currentTagsStr = currentWorkItem.fields?.['System.Tags'] || '';
document.push({
op: currentTagsStr ? 'replace' : 'add',
path: '/fields/System.Tags',
value: options.tags.length > 0 ? options.tags.join('; ') : '',
});
}
else if ((options.tagsToAdd && options.tagsToAdd.length > 0) ||
(options.tagsToRemove && options.tagsToRemove.length > 0)) {
const currentWorkItem = await witApi.getWorkItem(workItemId, [
'System.Tags',
]);
if (!currentWorkItem) {
throw new errors_1.AzureDevOpsResourceNotFoundError(`Work item '${workItemId}' not found`);
}
const currentTagsStr = currentWorkItem.fields?.['System.Tags'] || '';
let tagsList = currentTagsStr
.split(';')
.map((t) => t.trim())
.filter((t) => t.length > 0);
if (options.tagsToAdd) {
for (const tag of options.tagsToAdd) {
const trimmed = tag.trim();
const trimmedLower = trimmed.toLowerCase();
if (trimmed &&
!tagsList.some((t) => t.toLowerCase() === trimmedLower)) {
tagsList.push(trimmed);
}
}
}
if (options.tagsToRemove) {
const toRemove = new Set(options.tagsToRemove.map((t) => t.trim().toLowerCase()));
tagsList = tagsList.filter((t) => !toRemove.has(t.toLowerCase()));
}
document.push({
op: currentTagsStr ? 'replace' : 'add',
path: '/fields/System.Tags',
value: tagsList.length > 0 ? tagsList.join('; ') : '',
});
}
// Add any additional fields
if (options.additionalFields) {
for (const [key, value] of Object.entries(options.additionalFields)) {
document.push({
op: 'add',
path: `/fields/${key}`,
value: value,
});
}
}
// If no fields to update, throw an error
if (document.length === 0) {
throw new Error('At least one field must be provided for update');
}
// Update the work item
const updatedWorkItem = await witApi.updateWorkItem({}, // customHeaders
document, workItemId, undefined, // project
false, // validateOnly
false, // bypassRules
false, // suppressNotifications
WorkItemTrackingInterfaces_1.WorkItemExpand.All);
if (!updatedWorkItem) {
throw new errors_1.AzureDevOpsResourceNotFoundError(`Work item '${workItemId}' not found`);
}
return updatedWorkItem;
}
catch (error) {
if (error instanceof errors_1.AzureDevOpsError) {
throw error;
}
throw new Error(`Failed to update work item: ${error instanceof Error ? error.message : String(error)}`);
}
}
//# sourceMappingURL=feature.js.map