Skip to main content
Glama
ennuiii

Azure DevOps MCP Server with PAT Authentication

by ennuiii

testplan_create_test_case

Creates a test case work item in Azure DevOps by defining project, title, steps, priority, area path, and iteration path. Streamlines test case management via PAT authentication.

Instructions

Creates a new test case work item.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
areaPathNoThe area path for the test case.
iterationPathNoThe iteration path for the test case.
priorityNoThe priority of the test case.
projectYesThe unique identifier (ID or name) of the Azure DevOps project.
stepsNoThe steps to reproduce the test case. Make sure to format each step as '1. Step one|Expected result one 2. Step two|Expected result two. USE '|' as the delimiter between step and expected result. DO NOT use '|' in the description of the step or expected result.
titleYesThe title of the test case.

Implementation Reference

  • Handler function that creates a Test Case work item using the Azure DevOps Work Item Tracking API. Constructs a JSON patch document with title, steps (converted to XML), priority, areaPath, and iterationPath. Returns the created work item as JSON.
    async ({ project, title, steps, priority, areaPath, iterationPath }) => { const connection = await connectionProvider(); const witClient = await connection.getWorkItemTrackingApi(); let stepsXml; if (steps) { stepsXml = convertStepsToXml(steps); } // Create JSON patch document for work item const patchDocument = []; patchDocument.push({ op: "add", path: "/fields/System.Title", value: title, }); if (stepsXml) { patchDocument.push({ op: "add", path: "/fields/Microsoft.VSTS.TCM.Steps", value: stepsXml, }); } if (priority) { patchDocument.push({ op: "add", path: "/fields/Microsoft.VSTS.Common.Priority", value: priority, }); } if (areaPath) { patchDocument.push({ op: "add", path: "/fields/System.AreaPath", value: areaPath, }); } if (iterationPath) { patchDocument.push({ op: "add", path: "/fields/System.IterationPath", value: iterationPath, }); } const workItem = await witClient.createWorkItem({}, patchDocument, project, "Test Case"); return { content: [{ type: "text", text: JSON.stringify(workItem, null, 2) }], }; }
  • Zod input schema defining parameters for creating a test case: project, title, optional steps (formatted string), priority, areaPath, iterationPath.
    project: z.string().describe("The unique identifier (ID or name) of the Azure DevOps project."), title: z.string().describe("The title of the test case."), steps: z .string() .optional() .describe( "The steps to reproduce the test case. Make sure to format each step as '1. Step one|Expected result one\n2. Step two|Expected result two. USE '|' as the delimiter between step and expected result. DO NOT use '|' in the description of the step or expected result." ), priority: z.number().optional().describe("The priority of the test case."), areaPath: z.string().optional().describe("The area path for the test case."), iterationPath: z.string().optional().describe("The iteration path for the test case."), },
  • Registration of the 'testplan_create_test_case' tool on the MCP server using server.tool(), referencing Test_Plan_Tools.create_test_case as the tool name, with description, input schema, and handler function.
    server.tool( Test_Plan_Tools.create_test_case, "Creates a new test case work item.", { project: z.string().describe("The unique identifier (ID or name) of the Azure DevOps project."), title: z.string().describe("The title of the test case."), steps: z .string() .optional() .describe( "The steps to reproduce the test case. Make sure to format each step as '1. Step one|Expected result one\n2. Step two|Expected result two. USE '|' as the delimiter between step and expected result. DO NOT use '|' in the description of the step or expected result." ), priority: z.number().optional().describe("The priority of the test case."), areaPath: z.string().optional().describe("The area path for the test case."), iterationPath: z.string().optional().describe("The iteration path for the test case."), }, async ({ project, title, steps, priority, areaPath, iterationPath }) => { const connection = await connectionProvider(); const witClient = await connection.getWorkItemTrackingApi(); let stepsXml; if (steps) { stepsXml = convertStepsToXml(steps); } // Create JSON patch document for work item const patchDocument = []; patchDocument.push({ op: "add", path: "/fields/System.Title", value: title, }); if (stepsXml) { patchDocument.push({ op: "add", path: "/fields/Microsoft.VSTS.TCM.Steps", value: stepsXml, }); } if (priority) { patchDocument.push({ op: "add", path: "/fields/Microsoft.VSTS.Common.Priority", value: priority, }); } if (areaPath) { patchDocument.push({ op: "add", path: "/fields/System.AreaPath", value: areaPath, }); } if (iterationPath) { patchDocument.push({ op: "add", path: "/fields/System.IterationPath", value: iterationPath, }); } const workItem = await witClient.createWorkItem({}, patchDocument, project, "Test Case"); return { content: [{ type: "text", text: JSON.stringify(workItem, null, 2) }], }; } );
  • Helper function to parse steps string and generate XML for the Microsoft.VSTS.TCM.Steps field in test case work items.
    function convertStepsToXml(steps: string): string { // Accepts steps in the format: '1. Step one|Expected result one\n2. Step two|Expected result two' const stepsLines = steps.split("\n").filter((line) => line.trim() !== ""); let xmlSteps = `<steps id="0" last="${stepsLines.length}">`; for (let i = 0; i < stepsLines.length; i++) { const stepLine = stepsLines[i].trim(); if (stepLine) { // Split step and expected result by '|', fallback to default if not provided const [stepPart, expectedPart] = stepLine.split("|").map((s) => s.trim()); const stepMatch = stepPart.match(/^(\d+)\.\s*(.+)$/); const stepText = stepMatch ? stepMatch[2] : stepPart; const expectedText = expectedPart || "Verify step completes successfully"; xmlSteps += ` <step id="${i + 1}" type="ActionStep"> <parameterizedString isformatted="true">${escapeXml(stepText)}</parameterizedString> <parameterizedString isformatted="true">${escapeXml(expectedText)}</parameterizedString> </step>`; } } xmlSteps += "</steps>"; return xmlSteps; }
  • Utility function to escape XML special characters, used in convertStepsToXml.
    function escapeXml(unsafe: string): string { return unsafe.replace(/[<>&'"]/g, (c) => { switch (c) { case "<": return "&lt;"; case ">": return "&gt;"; case "&": return "&amp;"; case "'": return "&apos;"; case '"': return "&quot;"; default: return c; } }); }

Other Tools

Related Tools

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/ennuiii/DevOpsMcpPAT'

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