Skip to main content
Glama
workItems.ts8.02 kB
import { DEFAULT_PROJECT } from "../config/env.js"; import { getWorkItemClient } from "../auth/client.js"; import { logError } from "../utils/error.js"; import { listWorkItemsSchema, getWorkItemSchema, createWorkItemSchema, type ListWorkItemsParams, type GetWorkItemParams, type CreateWorkItemParams, } from "../schemas/workItems.js"; import * as WorkItemInterfaces from "azure-devops-node-api/interfaces/WorkItemTrackingInterfaces.js"; /** * List work items in a project */ export async function listWorkItems(rawParams: any) { // Parse arguments with defaults from environment variables const params = listWorkItemsSchema.parse({ project: rawParams.project || DEFAULT_PROJECT, types: rawParams.types, states: rawParams.states, assignedTo: rawParams.assignedTo, }); console.error("[API] Listing work items:", params); try { // Get the Work Item Tracking API client const witClient = await getWorkItemClient(); // Build WIQL query let wiql = `SELECT [System.Id], [System.Title], [System.State], [System.WorkItemType], [System.AssignedTo] FROM WorkItems WHERE [System.TeamProject] = '${params.project}'`; if (params.types && params.types.length > 0) { wiql += ` AND [System.WorkItemType] IN ('${params.types.join("','")}')`; } if (params.states && params.states.length > 0) { wiql += ` AND [System.State] IN ('${params.states.join("','")}')`; } if (params.assignedTo) { wiql += ` AND [System.AssignedTo] = '${params.assignedTo}'`; } // Execute the query const queryResult = await witClient.queryByWiql({ query: wiql }); if (!queryResult.workItems) { return { content: [{ type: "text", text: JSON.stringify([], null, 2) }], }; } // Get full work item details const workItems = await witClient.getWorkItems( queryResult.workItems.map( (wi: WorkItemInterfaces.WorkItemReference) => wi.id! ), undefined, undefined ); return { content: [ { type: "text", text: JSON.stringify(workItems, null, 2), }, ], }; } catch (error) { logError("Error listing work items", error); throw error; } } /** * Get details of a specific work item */ export async function getWorkItem(rawParams: any) { // Parse arguments with defaults from environment variables const params = getWorkItemSchema.parse({ project: rawParams.project || DEFAULT_PROJECT, id: rawParams.id, }); console.error("[API] Getting work item details:", params); try { // Get the Work Item Tracking API client const witClient = await getWorkItemClient(); // Get work item details const workItem = await witClient.getWorkItem( params.id, undefined, undefined ); return { content: [ { type: "text", text: JSON.stringify(workItem, null, 2), }, ], }; } catch (error) { logError("Error getting work item", error); throw error; } } /** * Create a new work item */ export async function createWorkItem(rawParams: any) { // Parse arguments with defaults from environment variables const params = createWorkItemSchema.parse({ project: rawParams.project || DEFAULT_PROJECT, type: rawParams.type, title: rawParams.title, description: rawParams.description, assignedTo: rawParams.assignedTo, technologyInvestmentType: rawParams.technologyInvestmentType, securityVulnerability: rawParams.securityVulnerability, }); console.error("[API] Creating work item:", params); // Specific validation for 'Feature' type if (params.type === "Feature") { if (!params.technologyInvestmentType) { throw new Error( "Field 'technologyInvestmentType' is required for work item type 'Feature'." ); } if (!params.securityVulnerability) { throw new Error( "Field 'securityVulnerability' is required for work item type 'Feature'." ); } } try { // Get the Work Item Tracking API client const witClient = await getWorkItemClient(); // Create patch operations for the work item const patchOperations = [ // Removed explicit type annotation { op: "add", path: "/fields/System.Title", value: params.title, }, ]; // Conditionally add optional fields if (params.technologyInvestmentType) { patchOperations.push({ op: "add", path: "/fields/Technology Investment Type", // Assuming field name value: params.technologyInvestmentType, }); } if (params.securityVulnerability) { patchOperations.push({ op: "add", path: "/fields/Security Vulnerability", // Assuming field name value: params.securityVulnerability, }); } if (params.description) { patchOperations.push({ op: "add", path: "/fields/System.Description", value: params.description, }); } if (params.assignedTo) { patchOperations.push({ op: "add", path: "/fields/System.AssignedTo", value: params.assignedTo, }); } // Create the work item const workItem = await witClient.createWorkItem( undefined, patchOperations, params.project, params.type ); return { content: [ { type: "text", text: JSON.stringify(workItem, null, 2), }, ], }; } catch (error) { logError("Error creating work item", error); throw error; } } /** * Tool definitions for work items */ export const workItemTools = [ { name: "list_work_items", description: "List work items in a project", inputSchema: { type: "object", properties: { project: { type: "string", description: "Name of the Azure DevOps project", }, types: { type: "array", items: { type: "string" }, description: "Filter by work item types", }, states: { type: "array", items: { type: "string" }, description: "Filter by states", }, assignedTo: { type: "string", description: "Filter by assigned user", }, }, required: ["project"], }, }, { name: "get_work_item", description: "Get details of a specific work item", inputSchema: { type: "object", properties: { project: { type: "string", description: "Name of the Azure DevOps project", }, id: { type: "number", description: "ID of the work item", }, }, required: ["project", "id"], }, }, { name: "create_work_item", description: "Create a new work item", inputSchema: { type: "object", properties: { project: { type: "string", description: "Name of the Azure DevOps project", }, type: { type: "string", description: "Type of work item (e.g., 'Task', 'Bug')", }, title: { type: "string", description: "Title of the work item", }, description: { type: "string", description: "Description of the work item", }, assignedTo: { type: "string", description: "User to assign the work item to", }, technologyInvestmentType: { type: "string", description: "The Technology Investment Type for the work item (Required for Features)", // Updated description }, securityVulnerability: { type: "string", description: "The Security Vulnerability status for the work item (Required for Features)", // Updated description }, }, required: ["project", "type", "title"], // Removed optional fields from required }, }, ];

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/mmruesch12/azdo-mcp'

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