search_wiki
Search for specific content across wiki pages within an Azure DevOps project. Apply filters, enable faceting, and manage pagination to refine and retrieve relevant information efficiently.
Instructions
Search for content across wiki pages in a project
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| filters | No | Optional filters to narrow search results | |
| includeFacets | No | Whether to include faceting in results (default: true) | |
| projectId | Yes | The ID or name of the project to search in | |
| searchText | Yes | The text to search for in wikis | |
| skip | No | Number of results to skip for pagination (default: 0) | |
| top | No | Number of results to return (default: 100, max: 1000) |
Input Schema (JSON Schema)
{
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"filters": {
"additionalProperties": false,
"description": "Optional filters to narrow search results",
"properties": {
"Project": {
"description": "Filter by project names",
"items": {
"type": "string"
},
"type": "array"
}
},
"type": "object"
},
"includeFacets": {
"default": true,
"description": "Whether to include faceting in results (default: true)",
"type": "boolean"
},
"projectId": {
"description": "The ID or name of the project to search in",
"type": "string"
},
"searchText": {
"description": "The text to search for in wikis",
"type": "string"
},
"skip": {
"default": 0,
"description": "Number of results to skip for pagination (default: 0)",
"minimum": 0,
"type": "integer"
},
"top": {
"default": 100,
"description": "Number of results to return (default: 100, max: 1000)",
"maximum": 1000,
"minimum": 1,
"type": "integer"
}
},
"required": [
"searchText",
"projectId"
],
"type": "object"
}
Implementation Reference
- Core handler function that performs wiki page search in Azure DevOps using the search API, handles authentication with Azure credentials or PAT, constructs search request, makes POST to almsearch.dev.azure.com, and wraps errors appropriately.export async function searchWiki( connection: WebApi, options: SearchWikiOptions, ): Promise<WikiSearchResponse> { try { // Prepare the search request const searchRequest: WikiSearchRequest = { searchText: options.searchText, $skip: options.skip, $top: options.top, filters: options.projectId ? { Project: [options.projectId], } : {}, includeFacets: options.includeFacets, }; // Add custom filters if provided if ( options.filters && options.filters.Project && options.filters.Project.length > 0 ) { if (!searchRequest.filters) { searchRequest.filters = {}; } if (!searchRequest.filters.Project) { searchRequest.filters.Project = []; } searchRequest.filters.Project = [ ...(searchRequest.filters.Project || []), ...options.filters.Project, ]; } // Get the authorization header from the connection const authHeader = await getAuthorizationHeader(); // Extract organization and project from the connection URL const { organization, project } = extractOrgAndProject( connection, options.projectId, ); // Make the search API request // If projectId is provided, include it in the URL, otherwise perform organization-wide search const searchUrl = options.projectId ? `https://almsearch.dev.azure.com/${organization}/${project}/_apis/search/wikisearchresults?api-version=7.1` : `https://almsearch.dev.azure.com/${organization}/_apis/search/wikisearchresults?api-version=7.1`; const searchResponse = await axios.post<WikiSearchResponse>( 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 return is never reached but helps TypeScript understand the control flow return null as never; } // Otherwise, wrap it in a generic error throw new AzureDevOpsError( `Failed to search wiki: ${error instanceof Error ? error.message : String(error)}`, ); } }
- Zod input schema validation for the search_wiki tool parameters.export const SearchWikiSchema = z.object({ searchText: z.string().describe('The text to search for in wikis'), 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 (Default: ${defaultProject}). If not provided, the default project will be used.`, ), filters: z .object({ Project: z .array(z.string()) .optional() .describe('Filter by project names'), }) .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)'), });
- src/features/search/tool-definitions.ts:18-22 (registration)Registration of the search_wiki tool in the searchTools array, defining name, description, and converting Zod schema to JSON schema for MCP.{ name: 'search_wiki', description: 'Search for content across wiki pages in a project', inputSchema: zodToJsonSchema(SearchWikiSchema), },
- src/features/search/index.ts:51-56 (registration)Dispatch handler in search feature that routes search_wiki requests, parses args with schema, calls searchWiki, and formats response for MCP.case 'search_wiki': { const args = SearchWikiSchema.parse(request.params.arguments); const result = await searchWiki(connection, args); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], };
- src/features/search/types.ts:123-165 (schema)TypeScript interface defining the options for SearchWikiOptions, used as input type for the handler.export interface SearchWikiOptions { /** * The text to search for within wiki pages */ searchText: 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. */ Project?: 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; }