search_work_items
Search and retrieve work items from Azure DevOps projects with text queries and filters. Narrow results by project, work item type, state, assigned user, or area path. Control pagination, sorting, and faceting.
Instructions
Search for work items across projects in Azure DevOps
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| searchText | Yes | The text to search for in work items | |
| organizationId | No | The ID or name of the organization (Default: mycompany) | |
| projectId | No | The ID or name of the project to search in. If omitted, the search runs across the organization when supported. | |
| filters | No | Optional filters to narrow search results | |
| top | No | Number of results to return (default: 100, max: 1000) | |
| skip | No | Number of results to skip for pagination (default: 0) | |
| includeFacets | No | Whether to include faceting in results (default: true) | |
| orderBy | No | Options for sorting search results |
Implementation Reference
- The main handler function for the 'search_work_items' tool. It builds a search request, gets authorization, resolves base URLs, and calls the Azure DevOps Search API to find work items.
export async function searchWorkItems( connection: WebApi, options: SearchWorkItemsOptions, ): Promise<WorkItemSearchResponse> { try { // Prepare the search request const searchRequest: WorkItemSearchRequest = { searchText: options.searchText, $skip: options.skip, $top: options.top, filters: { ...(options.projectId ? { 'System.TeamProject': [options.projectId] } : {}), ...options.filters, }, includeFacets: options.includeFacets, $orderBy: options.orderBy, }; // Get the authorization header from the connection const authHeader = await getAuthorizationHeader(); const baseUrls = resolveAzureDevOpsBaseUrls(connection.serverUrl, { organizationId: options.organizationId, projectId: options.projectId, }); if (baseUrls.type === 'server' && !options.projectId) { throw new AzureDevOpsValidationError( 'Project ID is required for Azure DevOps Server work item search', ); } // Make the search API request // If projectId is provided, include it in the URL, otherwise perform organization-wide search const searchUrl = options.projectId ? `${baseUrls.searchBaseUrl}/${options.projectId}/_apis/search/workitemsearchresults?api-version=7.1` : `${baseUrls.searchBaseUrl}/_apis/search/workitemsearchresults?api-version=7.1`; const searchResponse = await axios.post<WorkItemSearchResponse>( searchUrl, searchRequest, { headers: { Authorization: authHeader, 'Content-Type': 'application/json', }, }, ); return searchResponse.data; } catch (error) { // If it's already an AzureDevOpsError, rethrow it if (error instanceof AzureDevOpsError) { throw error; } // Handle axios errors if (axios.isAxiosError(error)) { const status = error.response?.status; const message = error.response?.data?.message || error.message; if (status === 404) { throw new AzureDevOpsResourceNotFoundError( `Resource not found: ${message}`, ); } else if (status === 400) { throw new AzureDevOpsValidationError( `Invalid request: ${message}`, error.response?.data, ); } else if (status === 401 || status === 403) { throw new AzureDevOpsPermissionError(`Permission denied: ${message}`); } else { // For other axios errors, wrap in a generic AzureDevOpsError throw new AzureDevOpsError(`Azure DevOps API error: ${message}`); } // This code is unreachable but TypeScript doesn't know that } // Otherwise, wrap it in a generic error throw new AzureDevOpsError( `Failed to search work items: ${error instanceof Error ? error.message : String(error)}`, ); } } - Zod schema defining the input validation for search_work_items, including searchText, organizationId, projectId, filters (System.TeamProject, System.WorkItemType, System.State, System.AssignedTo, System.AreaPath), top, skip, includeFacets, and orderBy.
export const SearchWorkItemsSchema = z.object({ searchText: z.string().describe('The text to search for in work items'), organizationId: z .string() .optional() .describe(`The ID or name of the organization (Default: ${defaultOrg})`), projectId: z .string() .optional() .describe( 'The ID or name of the project to search in. If omitted, the search runs across the organization when supported.', ), filters: z .object({ 'System.TeamProject': z .array(z.string()) .optional() .describe('Filter by project names'), 'System.WorkItemType': z .array(z.string()) .optional() .describe('Filter by work item types (Bug, Task, User Story, etc.)'), 'System.State': z .array(z.string()) .optional() .describe('Filter by work item states (New, Active, Closed, etc.)'), 'System.AssignedTo': z .array(z.string()) .optional() .describe('Filter by assigned users'), 'System.AreaPath': z .array(z.string()) .optional() .describe('Filter by area paths'), }) .optional() .describe('Optional filters to narrow search results'), top: z .number() .int() .min(1) .max(1000) .default(100) .describe('Number of results to return (default: 100, max: 1000)'), skip: z .number() .int() .min(0) .default(0) .describe('Number of results to skip for pagination (default: 0)'), includeFacets: z .boolean() .default(true) .describe('Whether to include faceting in results (default: true)'), orderBy: z .array( z.object({ field: z.string().describe('Field to sort by'), sortOrder: z.enum(['ASC', 'DESC']).describe('Sort order (ASC/DESC)'), }), ) .optional() .describe('Options for sorting search results'), }); - src/features/search/tool-definitions.ts:12-28 (registration)Tool definition registration for 'search_work_items' with its name, description, and JSON-schema input, exported as part of the searchTools array.
export const searchTools: ToolDefinition[] = [ { name: 'search_code', description: 'Search for code across repositories in a project', inputSchema: zodToJsonSchema(SearchCodeSchema), }, { name: 'search_wiki', description: 'Search for content across wiki pages in a project', inputSchema: zodToJsonSchema(SearchWikiSchema), }, { name: 'search_work_items', description: 'Search for work items across projects in Azure DevOps', inputSchema: zodToJsonSchema(SearchWorkItemsSchema), }, ]; - src/features/search/index.ts:58-68 (registration)Request routing in the search feature handler: dispatches 'search_work_items' requests by parsing args with SearchWorkItemsSchema and calling searchWorkItems.
case 'search_work_items': { const args = SearchWorkItemsSchema.parse(request.params.arguments); const result = await searchWorkItems(connection, args); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], }; } default: throw new Error(`Unknown search tool: ${request.params.name}`); } }; - src/features/search/types.ts:364-617 (helper)TypeScript type definitions for SearchWorkItemsOptions, WorkItemSearchRequest, WorkItemSearchResponse, WorkItemResult, and WorkItemHit used by the searchWorkItems handler.
export interface SearchWorkItemsOptions { /** * The text to search for within work items */ searchText: string; /** * The ID or name of the organization */ organizationId?: string; /** * The ID or name of the project to search in * If not provided, search will be performed across the entire organization */ projectId?: string; /** * Optional filters to narrow search results */ filters?: { /** * Filter by project names. Useful for cross-project searches. */ 'System.TeamProject'?: string[]; /** * Filter by work item types (Bug, Task, User Story, etc.) */ 'System.WorkItemType'?: string[]; /** * Filter by work item states (New, Active, Closed, etc.) */ 'System.State'?: string[]; /** * Filter by assigned users */ 'System.AssignedTo'?: string[]; /** * Filter by area paths */ 'System.AreaPath'?: string[]; }; /** * Number of results to return * @default 100 * @minimum 1 * @maximum 1000 */ top?: number; /** * Number of results to skip for pagination * @default 0 * @minimum 0 */ skip?: number; /** * Whether to include faceting in results * @default true */ includeFacets?: boolean; /** * Options for sorting search results * If null, results are sorted by relevance */ orderBy?: SortOption[]; } /** * Request body for the Azure DevOps Work Item Search API */ export interface WorkItemSearchRequest { /** * The search text to find in work items */ searchText: string; /** * Number of results to skip for pagination */ $skip?: number; /** * Number of results to return */ $top?: number; /** * Filters to be applied. Set to null if no filters are needed. */ filters?: { 'System.TeamProject'?: string[]; 'System.WorkItemType'?: string[]; 'System.State'?: string[]; 'System.AssignedTo'?: string[]; 'System.AreaPath'?: string[]; }; /** * Options for sorting search results * If null, results are sorted by relevance */ $orderBy?: SortOption[]; /** * Whether to include faceting in the result * @default false */ includeFacets?: boolean; } /** * Defines the matched terms in the field of the work item result */ export interface WorkItemHit { /** * Reference name of the highlighted field */ fieldReferenceName: string; /** * Matched/highlighted snippets of the field */ highlights: string[]; } /** * Defines the work item result that matched a work item search request */ export interface WorkItemResult { /** * Project details of the work item */ project: { /** * ID of the project */ id: string; /** * Name of the project */ name: string; }; /** * A standard set of work item fields and their values */ fields: { /** * ID of the work item */ 'system.id': string; /** * Type of the work item (Bug, Task, User Story, etc.) */ 'system.workitemtype': string; /** * Title of the work item */ 'system.title': string; /** * User assigned to the work item */ 'system.assignedto'?: string; /** * Current state of the work item */ 'system.state'?: string; /** * Tags associated with the work item */ 'system.tags'?: string; /** * Revision number of the work item */ 'system.rev'?: string; /** * Creation date of the work item */ 'system.createddate'?: string; /** * Last modified date of the work item */ 'system.changeddate'?: string; /** * Other fields may be included based on the work item type */ [key: string]: string | number | boolean | null | undefined; }; /** * Highlighted snippets of fields that match the search request * The list is sorted by relevance of the snippets */ hits: WorkItemHit[]; /** * URL to the work item */ url: string; } /** * Defines a work item search response item */ export interface WorkItemSearchResponse { /** * Total number of matched work items */ count: number; /** * List of top matched work items */ results: WorkItemResult[]; /** * Numeric code indicating additional information: * 0 - Ok * 1 - Account is being reindexed * 2 - Account indexing has not started * 3 - Invalid Request * ... and others as defined in the API */ infoCode?: number; /** * A dictionary storing an array of Filter objects against each facet */ facets?: { 'System.TeamProject'?: CodeSearchFacet[]; 'System.WorkItemType'?: CodeSearchFacet[]; 'System.State'?: CodeSearchFacet[]; 'System.AssignedTo'?: CodeSearchFacet[]; 'System.AreaPath'?: CodeSearchFacet[]; }; }