Skip to main content
Glama

search_code

Locate specific code across repositories within a project. Apply filters like branch, code element, file path, or repository to refine results and include full file content or snippets.

Instructions

Search for code across repositories in a project

Input Schema

NameRequiredDescriptionDefault
filtersNoOptional filters to narrow search results
includeContentNoWhether to include full file content in results (default: true)
includeSnippetNoWhether to include code snippets in results (default: true)
projectIdYesThe ID or name of the project to search in
searchTextYesThe text to search for
skipNoNumber of results to skip for pagination (default: 0)
topNoNumber 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": { "Branch": { "description": "Filter by branch names", "items": { "type": "string" }, "type": "array" }, "CodeElement": { "description": "Filter by code element types (function, class, etc.)", "items": { "type": "string" }, "type": "array" }, "Path": { "description": "Filter by file paths", "items": { "type": "string" }, "type": "array" }, "Repository": { "description": "Filter by repository names", "items": { "type": "string" }, "type": "array" } }, "type": "object" }, "includeContent": { "default": true, "description": "Whether to include full file content in results (default: true)", "type": "boolean" }, "includeSnippet": { "default": true, "description": "Whether to include code snippets 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", "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 executes the code search using Azure DevOps Search API, handles authentication, makes API calls, and optionally enriches results with file contents.
    export async function searchCode( connection: WebApi, options: SearchCodeOptions, ): Promise<CodeSearchResponse> { try { // When includeContent is true, limit results to prevent timeouts const top = options.includeContent ? Math.min(options.top || 10, 10) : options.top; // Get the project ID (either provided or default) const projectId = options.projectId || process.env.AZURE_DEVOPS_DEFAULT_PROJECT; if (!projectId) { throw new AzureDevOpsValidationError( 'Project ID is required. Either provide a projectId or set the AZURE_DEVOPS_DEFAULT_PROJECT environment variable.', ); } // Prepare the search request const searchRequest: CodeSearchRequest = { searchText: options.searchText, $skip: options.skip, $top: top, // Use limited top value when includeContent is true filters: { Project: [projectId], ...(options.filters || {}), }, includeFacets: true, includeSnippet: options.includeSnippet, }; // Get the authorization header from the connection const authHeader = await getAuthorizationHeader(); // Extract organization from the connection URL const { organization } = extractOrgFromUrl(connection); // Make the search API request with the project ID const searchUrl = `https://almsearch.dev.azure.com/${organization}/${projectId}/_apis/search/codesearchresults?api-version=7.1`; const searchResponse = await axios.post<CodeSearchResponse>( searchUrl, searchRequest, { headers: { Authorization: authHeader, 'Content-Type': 'application/json', }, }, ); const results = searchResponse.data; // If includeContent is true, fetch the content for each result if (options.includeContent && results.results.length > 0) { await enrichResultsWithContent(connection, results.results); } return results; } catch (error) { if (error instanceof AzureDevOpsError) { throw error; } if (axios.isAxiosError(error)) { const status = error.response?.status; if (status === 404) { throw new AzureDevOpsResourceNotFoundError( 'Repository or project not found', { cause: error }, ); } if (status === 400) { throw new AzureDevOpsValidationError( 'Invalid search parameters', error.response?.data, { cause: error }, ); } if (status === 401) { throw new AzureDevOpsAuthenticationError('Authentication failed', { cause: error, }); } if (status === 403) { throw new AzureDevOpsPermissionError( 'Permission denied to access repository', { cause: error }, ); } } throw new AzureDevOpsError('Failed to search code', { cause: error }); } }
  • Zod schema for input validation of the search_code tool parameters.
    export const SearchCodeSchema = z .object({ searchText: z.string().describe('The text to search for'), 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({ Repository: z .array(z.string()) .optional() .describe('Filter by repository names'), Path: z.array(z.string()).optional().describe('Filter by file paths'), Branch: z .array(z.string()) .optional() .describe('Filter by branch names'), CodeElement: z .array(z.string()) .optional() .describe('Filter by code element types (function, class, etc.)'), }) .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)'), includeSnippet: z .boolean() .default(true) .describe('Whether to include code snippets in results (default: true)'), includeContent: z .boolean() .default(true) .describe( 'Whether to include full file content in results (default: true)', ), }) .transform((data) => { return { ...data, organizationId: data.organizationId ?? defaultOrg, projectId: data.projectId ?? defaultProject, }; });
  • Registration of the search_code tool in the tools list, including name, description, and JSON schema derived from Zod.
    { name: 'search_code', description: 'Search for code across repositories in a project', inputSchema: zodToJsonSchema(SearchCodeSchema), },
  • Request handler dispatch for search_code tool, parsing arguments and calling the searchCode handler.
    case 'search_code': { const args = SearchCodeSchema.parse(request.params.arguments); const result = await searchCode(connection, args); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], }; }
  • Helper function to enrich search results with full file contents using the Azure DevOps Git API.
    async function enrichResultsWithContent( connection: WebApi, results: CodeSearchResult[], ): Promise<void> { try { const gitApi = await connection.getGitApi(); // Process each result in parallel await Promise.all( results.map(async (result) => { try { // Get the file content using the Git API // Pass only the required parameters to avoid the "path" and "scopePath" conflict const contentStream = await gitApi.getItemContent( result.repository.id, result.path, result.project.name, undefined, // No version descriptor object undefined, // No recursion level undefined, // Don't include content metadata undefined, // No latest processed change false, // Don't download { version: result.versions[0]?.changeId, versionType: GitVersionType.Commit, }, // Version descriptor true, // Include content ); // Convert the stream to a string and store it in the result if (contentStream) { // Since getItemContent always returns NodeJS.ReadableStream, we need to read the stream const chunks: Buffer[] = []; // Listen for data events to collect chunks contentStream.on('data', (chunk) => { chunks.push(Buffer.from(chunk)); }); // Use a promise to wait for the stream to finish result.content = await new Promise<string>((resolve, reject) => { contentStream.on('end', () => { // Concatenate all chunks and convert to string const buffer = Buffer.concat(chunks); resolve(buffer.toString('utf8')); }); contentStream.on('error', (err) => { reject(err); }); }); } } catch (error) { // Log the error but don't fail the entire operation console.error( `Failed to fetch content for ${result.path}: ${error instanceof Error ? error.message : String(error)}`, ); } }), ); } catch (error) { // Log the error but don't fail the entire operation console.error( `Failed to enrich results with content: ${error instanceof Error ? error.message : String(error)}`, ); } }

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