Skip to main content
Glama
Tiberriver256

Azure DevOps MCP Server

search_code

Search for code across Azure DevOps repositories using text queries with filters for repository, path, branch, and code element types to locate specific code segments.

Instructions

Search for code across repositories in a project

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
searchTextYesThe text to search for
organizationIdNoThe ID or name of the organization (Default: mycompany)
projectIdNoThe ID or name of the project to search in (Default: MyProject). If not provided, the default project will be used.
filtersNoOptional filters to narrow search results
topNoNumber of results to return (default: 100, max: 1000)
skipNoNumber of results to skip for pagination (default: 0)
includeSnippetNoWhether to include code snippets in results (default: true)
includeContentNoWhether to include full file content in results (default: true)

Implementation Reference

  • Core handler function that executes the code search logic using Azure DevOps Code Search API, handles authentication, fetches results, and optionally enriches 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 defining input validation and defaults for 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,
        };
      });
  • Tool definition registration for search_code, including name, description, and JSON schema derived from Zod schema.
    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),
      },
    ];
  • Request handler switch case that parses arguments with schema and calls the searchCode handler for 'search_code' tool.
    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) }],
      };
    }
  • TypeScript interface defining the options structure for the searchCode function, used in handler.
    export interface SearchCodeOptions {
      searchText: string;
      projectId?: string;
      filters?: {
        Repository?: string[];
        Path?: string[];
        Branch?: string[];
        CodeElement?: string[];
      };
      top?: number;
      skip?: number;
      includeSnippet?: boolean;
      includeContent?: boolean;
    }
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 doesn't mention whether this is a read-only operation (implied by 'search'), potential rate limits, authentication requirements, error conditions, or the format/scope of results (e.g., pagination details beyond schema parameters). For a search tool with 8 parameters, this leaves significant behavioral gaps.

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 front-loads the core purpose without unnecessary words. It wastes no space on repetition or fluff, making it easy to parse quickly. Every word earns its place by directly conveying the tool's function.

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 complexity (8 parameters, nested filters) and lack of both annotations and output schema, the description is insufficiently complete. It doesn't explain what the search returns (e.g., result structure, snippet/content inclusion implications), how filters interact, or behavioral aspects like performance or limitations. For a search tool with rich parameters, this leaves too much undefined for confident agent use.

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?

The schema description coverage is 100%, providing detailed documentation for all 8 parameters including defaults and constraints. The description adds no parameter-specific information beyond what's in the schema, such as search syntax examples or filter usage patterns. However, with complete schema coverage, the baseline score of 3 is appropriate as the schema adequately handles parameter semantics.

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 tool's purpose with a specific verb ('search') and resource ('code across repositories in a project'), making it immediately understandable. It distinguishes from siblings like 'search_wiki' and 'search_work_items' by specifying 'code' as the search target. However, it doesn't explicitly differentiate from potential code-search alternatives that might exist in other contexts.

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., authentication needs), compare with siblings like 'get_file_content' for specific file retrieval, or indicate when other search tools (e.g., 'search_wiki') would be more appropriate. The agent must infer usage from the name alone.

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