Skip to main content
Glama
Tiberriver256

Azure DevOps MCP Server

get_all_repositories_tree

Retrieve a hierarchical tree view of files and directories across multiple Azure DevOps repositories within a project, enabling users to explore repository structures and locate files efficiently.

Instructions

Displays a hierarchical tree view of files and directories across multiple Azure DevOps repositories within a project, based on their default branches

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
organizationIdNoThe ID or name of the Azure DevOps organization (Default: mycompany)
projectIdNoThe ID or name of the project (Default: MyProject)
repositoryPatternNoRepository name pattern (wildcard characters allowed) to filter which repositories are included
depthNoMaximum depth to traverse within each repository (0 = unlimited)
patternNoFile pattern (wildcard characters allowed) to filter files by within each repository

Implementation Reference

  • Core handler function that retrieves the tree structure of files/directories across multiple repositories in an Azure DevOps project, supporting depth limits, repository patterns, and file filtering.
    export async function getAllRepositoriesTree(
      connection: WebApi,
      options: GetAllRepositoriesTreeOptions,
    ): Promise<AllRepositoriesTreeResponse> {
      try {
        const gitApi = await connection.getGitApi();
        let repositories: GitRepository[] = [];
    
        // Get all repositories in the project
        repositories = await gitApi.getRepositories(options.projectId);
    
        // Filter repositories by name pattern if specified
        if (options.repositoryPattern) {
          repositories = repositories.filter((repo) =>
            minimatch(repo.name || '', options.repositoryPattern || '*'),
          );
        }
    
        // Initialize results array
        const results: RepositoryTreeResponse[] = [];
    
        // Process each repository
        for (const repo of repositories) {
          try {
            // Get default branch ref
            const defaultBranch = repo.defaultBranch;
            if (!defaultBranch) {
              // Skip repositories with no default branch
              results.push({
                name: repo.name || 'Unknown',
                tree: [],
                stats: { directories: 0, files: 0 },
                error: 'No default branch found',
              });
              continue;
            }
    
            // Clean the branch name (remove refs/heads/ prefix)
            const branchRef = defaultBranch.replace('refs/heads/', '');
    
            // Initialize tree items array and counters
            const treeItems: RepositoryTreeItem[] = [];
            const stats = { directories: 0, files: 0 };
    
            // Determine the recursion level and processing approach
            const depth = options.depth !== undefined ? options.depth : 0; // Default to 0 (max depth)
    
            if (depth === 0) {
              // For max depth (0), use server-side recursion for better performance
              const allItems = await gitApi.getItems(
                repo.id || '',
                options.projectId,
                '/',
                VersionControlRecursionType.Full, // Use full recursion
                true,
                false,
                false,
                false,
                {
                  version: branchRef,
                  versionType: GitVersionType.Branch,
                },
              );
    
              // Filter out the root item itself and bad items
              const itemsToProcess = allItems.filter(
                (item) =>
                  item.path !== '/' && item.gitObjectType !== GitObjectType.Bad,
              );
    
              // Process all items at once (they're already retrieved recursively)
              processItemsNonRecursive(
                itemsToProcess,
                treeItems,
                stats,
                options.pattern,
              );
            } else {
              // For limited depth, use the regular recursive approach
              // Get items at the root level
              const rootItems = await gitApi.getItems(
                repo.id || '',
                options.projectId,
                '/',
                VersionControlRecursionType.OneLevel,
                true,
                false,
                false,
                false,
                {
                  version: branchRef,
                  versionType: GitVersionType.Branch,
                },
              );
    
              // Filter out the root item itself and bad items
              const itemsToProcess = rootItems.filter(
                (item) =>
                  item.path !== '/' && item.gitObjectType !== GitObjectType.Bad,
              );
    
              // Process the root items and their children (up to specified depth)
              await processItems(
                gitApi,
                repo.id || '',
                options.projectId,
                itemsToProcess,
                branchRef,
                treeItems,
                stats,
                1,
                depth,
                options.pattern,
              );
            }
    
            // Add repository tree to results
            results.push({
              name: repo.name || 'Unknown',
              tree: treeItems,
              stats,
            });
          } catch (repoError) {
            // Handle errors for individual repositories
            results.push({
              name: repo.name || 'Unknown',
              tree: [],
              stats: { directories: 0, files: 0 },
              error: `Error processing repository: ${repoError instanceof Error ? repoError.message : String(repoError)}`,
            });
          }
        }
    
        return { repositories: results };
      } catch (error) {
        if (error instanceof AzureDevOpsError) {
          throw error;
        }
        throw new Error(
          `Failed to get repository tree: ${error instanceof Error ? error.message : String(error)}`,
        );
      }
    }
  • Zod schema defining the input parameters for the get_all_repositories_tree tool.
    export const GetAllRepositoriesTreeSchema = z.object({
      organizationId: z
        .string()
        .optional()
        .describe(
          `The ID or name of the Azure DevOps organization (Default: ${defaultOrg})`,
        ),
      projectId: z
        .string()
        .optional()
        .describe(`The ID or name of the project (Default: ${defaultProject})`),
      repositoryPattern: z
        .string()
        .optional()
        .describe(
          'Repository name pattern (wildcard characters allowed) to filter which repositories are included',
        ),
      depth: z
        .number()
        .int()
        .min(0)
        .max(10)
        .optional()
        .default(0)
        .describe(
          'Maximum depth to traverse within each repository (0 = unlimited)',
        ),
      pattern: z
        .string()
        .optional()
        .describe(
          'File pattern (wildcard characters allowed) to filter files by within each repository',
        ),
    });
  • Tool definition registration including name, description, and input schema conversion for MCP tool list.
    {
      name: 'get_all_repositories_tree',
      description:
        'Displays a hierarchical tree view of files and directories across multiple Azure DevOps repositories within a project, based on their default branches',
      inputSchema: zodToJsonSchema(GetAllRepositoriesTreeSchema),
    },
  • Request handler switch case that parses arguments with schema, calls the handler, formats output as ASCII tree, and returns response.
    case 'get_all_repositories_tree': {
      const args = GetAllRepositoriesTreeSchema.parse(request.params.arguments);
      const result = await getAllRepositoriesTree(connection, {
        ...args,
        projectId: args.projectId ?? defaultProject,
        organizationId: args.organizationId ?? defaultOrg,
      });
    
      // Format the output as plain text tree representation
      let formattedOutput = '';
      for (const repo of result.repositories) {
        formattedOutput += formatRepositoryTree(
          repo.name,
          repo.tree,
          repo.stats,
          repo.error,
        );
        formattedOutput += '\n'; // Add blank line between repositories
      }
    
      return {
        content: [{ type: 'text', text: formattedOutput }],
      };
    }
  • TypeScript interface matching the schema for handler options.
    export interface GetAllRepositoriesTreeOptions {
      organizationId: string;
      projectId: string;
      repositoryPattern?: string;
      depth?: number;
      pattern?: string;
    }

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