Skip to main content
Glama
Tiberriver256

Azure DevOps MCP Server

manage_work_item_link

Add, remove, or update links between Azure DevOps work items to establish relationships and track dependencies.

Instructions

Add or remove links between work items

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
sourceWorkItemIdYesThe ID of the source work item
targetWorkItemIdYesThe ID of the target work item
projectIdNoThe ID or name of the project (Default: MyProject)
organizationIdNoThe ID or name of the organization (Default: mycompany)
operationYesThe operation to perform on the link
relationTypeYesThe reference name of the relation type (e.g., "System.LinkTypes.Hierarchy-Forward")
newRelationTypeNoThe new relation type to use when updating a link
commentNoOptional comment explaining the link

Implementation Reference

  • The core handler function that manages (adds, removes, updates) links between two work items using Azure DevOps WorkItemTrackingApi. Handles input validation, constructs JSON patch documents for relations, and updates the source work item.
    export async function manageWorkItemLink(
      connection: WebApi,
      projectId: string,
      options: ManageWorkItemLinkOptions,
    ): Promise<WorkItem> {
      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}`;
    
        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/+[rel=${relationType};url=${relationshipUrl}]`,
            });
          }
    
          // 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/+[rel=${relationType};url=${relationshipUrl}]`,
          });
        }
    
        // Update the work item with the new relationship
        const updatedWorkItem = await witApi.updateWorkItem(
          {}, // customHeaders
          document,
          sourceWorkItemId,
          projectId,
        );
    
        if (!updatedWorkItem) {
          throw new AzureDevOpsResourceNotFoundError(
            `Work item '${sourceWorkItemId}' not found`,
          );
        }
    
        return updatedWorkItem;
      } catch (error) {
        if (error instanceof AzureDevOpsError) {
          throw error;
        }
        throw new Error(
          `Failed to manage work item link: ${error instanceof Error ? error.message : String(error)}`,
        );
      }
    }
  • Zod schema defining the input parameters for the manage_work_item_link tool, including source/target IDs, operation (add/remove/update), relation types, and optional fields.
    export const ManageWorkItemLinkSchema = z.object({
      sourceWorkItemId: z.number().describe('The ID of the source work item'),
      targetWorkItemId: z.number().describe('The ID of the target work item'),
      projectId: z
        .string()
        .optional()
        .describe(`The ID or name of the project (Default: ${defaultProject})`),
      organizationId: z
        .string()
        .optional()
        .describe(`The ID or name of the organization (Default: ${defaultOrg})`),
      operation: z
        .enum(['add', 'remove', 'update'])
        .describe('The operation to perform on the link'),
      relationType: z
        .string()
        .describe(
          'The reference name of the relation type (e.g., "System.LinkTypes.Hierarchy-Forward")',
        ),
      newRelationType: z
        .string()
        .optional()
        .describe('The new relation type to use when updating a link'),
      comment: z
        .string()
        .optional()
        .describe('Optional comment explaining the link'),
    });
  • MCP tool registration definition, specifying name, description, and input JSON schema derived from Zod schema.
      name: 'manage_work_item_link',
      description: 'Add or remove links between work items',
      inputSchema: zodToJsonSchema(ManageWorkItemLinkSchema),
    },
  • Runtime dispatch handler in the main work-items request handler that parses arguments with the schema and invokes the manageWorkItemLink function.
    case 'manage_work_item_link': {
      const args = ManageWorkItemLinkSchema.parse(request.params.arguments);
      const result = await manageWorkItemLink(
        connection,
        args.projectId ?? defaultProject,
        {
          sourceWorkItemId: args.sourceWorkItemId,
          targetWorkItemId: args.targetWorkItemId,
          operation: args.operation,
          relationType: args.relationType,
          newRelationType: args.newRelationType,
          comment: args.comment,
        },
      );
      return {
        content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
      };
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure but offers minimal information. It states the tool can 'add or remove links' (implying mutation), but doesn't clarify permissions required, whether operations are reversible, side effects, or error conditions. For a mutation tool with 8 parameters, this lack of behavioral context is a significant gap that could lead to incorrect usage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that directly states the tool's purpose without unnecessary words. It's front-loaded with the core action and resource, making it immediately scannable. Every word earns its place, achieving ideal conciseness for a basic description.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (mutation operation with 8 parameters, no annotations, and no output schema), the description is incomplete. It doesn't address behavioral aspects like authentication needs, rate limits, or what happens on success/failure. While the schema covers parameters well, the description fails to provide the contextual information needed for safe and effective use of this mutation tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all 8 parameters thoroughly. The description adds no parameter-specific information beyond what's in the schema (e.g., it doesn't explain what 'relationType' values mean or when 'newRelationType' is used). This meets the baseline of 3 since the schema does the heavy lifting, but the description doesn't compensate with additional semantic context.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Add or remove links') and resource ('between work items'), making the purpose immediately understandable. It distinguishes this tool from siblings like 'create_work_item' or 'update_work_item' by focusing on link management rather than work item creation/modification. However, it doesn't explicitly mention the 'update' operation that appears in the schema, leaving a minor gap in specificity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention prerequisites (e.g., needing existing work items), exclusions, or how it relates to sibling tools like 'update_work_item' or 'get_work_item'. The agent must infer usage solely from the tool name and parameters, which is insufficient for informed selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

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

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