Skip to main content
Glama
Tiberriver256

Azure DevOps MCP Server

get_file_content

Retrieve file or directory content from Azure DevOps repositories by specifying project, repository, path, and version parameters.

Instructions

Get content of a file or directory from a repository

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
projectIdNoThe ID or name of the project (Default: MyProject)
organizationIdNoThe ID or name of the organization (Default: mycompany)
repositoryIdYesThe ID or name of the repository
pathNoPath to the file or folder/
versionNoThe version (branch, tag, or commit) to get content from
versionTypeNoType of version specified (branch, commit, or tag)

Implementation Reference

  • Core handler function that retrieves file content or directory listing from an Azure DevOps Git repository using the Azure DevOps Node API.
    export async function getFileContent(
      connection: WebApi,
      projectId: string,
      repositoryId: string,
      path: string = '/',
      versionDescriptor?: { versionType: GitVersionType; version: string },
    ): Promise<FileContentResponse> {
      try {
        const gitApi = await connection.getGitApi();
    
        // Create version descriptor for API requests
        const gitVersionDescriptor: GitVersionDescriptor | undefined =
          versionDescriptor
            ? {
                version: versionDescriptor.version,
                versionType: versionDescriptor.versionType,
                versionOptions: undefined,
              }
            : undefined;
    
        // First, try to get items using the path to determine if it's a directory
        let isDirectory = false;
        let items: GitItem[] = [];
    
        try {
          items = await gitApi.getItems(
            repositoryId,
            projectId,
            path,
            VersionControlRecursionType.OneLevel,
            undefined,
            undefined,
            undefined,
            undefined,
            gitVersionDescriptor,
          );
    
          // If multiple items are returned or the path ends with /, it's a directory
          isDirectory = items.length > 1 || (path !== '/' && path.endsWith('/'));
        } catch {
          // If getItems fails, try to get file content directly
          isDirectory = false;
        }
    
        if (isDirectory) {
          // For directories, return a formatted list of the items
          return {
            content: JSON.stringify(items, null, 2),
            isDirectory: true,
          };
        } else {
          // For files, get the actual content
          try {
            // Get file content using the Git API
            const contentStream = await gitApi.getItemContent(
              repositoryId,
              path,
              projectId,
              undefined,
              undefined,
              undefined,
              undefined,
              false,
              gitVersionDescriptor,
              true,
            );
    
            // Convert the stream to a string
            if (contentStream) {
              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
              const 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);
                });
              });
    
              return {
                content,
                isDirectory: false,
              };
            }
    
            throw new Error('No content returned from API');
          } catch (error) {
            // If it's a 404 or similar error, throw a ResourceNotFoundError
            if (
              error instanceof Error &&
              (error.message.includes('not found') ||
                error.message.includes('does not exist'))
            ) {
              throw new AzureDevOpsResourceNotFoundError(
                `Path '${path}' not found in repository '${repositoryId}' of project '${projectId}'`,
              );
            }
            throw error;
          }
        }
      } catch (error) {
        // If it's already an AzureDevOpsResourceNotFoundError, rethrow it
        if (error instanceof AzureDevOpsResourceNotFoundError) {
          throw error;
        }
    
        // Otherwise, wrap it in a ResourceNotFoundError
        throw new AzureDevOpsResourceNotFoundError(
          `Failed to get content for path '${path}': ${error instanceof Error ? error.message : String(error)}`,
        );
      }
    }
  • Zod schema defining the input parameters for the get_file_content tool, including project, repo, path, and optional version details.
    export const GetFileContentSchema = z.object({
      projectId: z
        .string()
        .optional()
        .describe(`The ID or name of the project (Default: ${defaultProject})`),
      organizationId: z
        .string()
        .optional()
        .describe(`The ID or name of the organization (Default: ${defaultOrg})`),
      repositoryId: z.string().describe('The ID or name of the repository'),
      path: z
        .string()
        .optional()
        .default('/')
        .describe('Path to the file or folder'),
      version: z
        .string()
        .optional()
        .describe('The version (branch, tag, or commit) to get content from'),
      versionType: z
        .enum(['branch', 'commit', 'tag'])
        .optional()
        .describe('Type of version specified (branch, commit, or tag)'),
    });
  • Registration of the get_file_content tool in the repositoriesTools array, specifying name, description, and input schema.
      name: 'get_file_content',
      description: 'Get content of a file or directory from a repository',
      inputSchema: zodToJsonSchema(GetFileContentSchema),
    },
  • Dispatcher in handleRepositoriesRequest that parses arguments with the schema and invokes the getFileContent handler for MCP tool calls.
    case 'get_file_content': {
      const args = GetFileContentSchema.parse(request.params.arguments);
    
      // Map the string version type to the GitVersionType enum
      let versionTypeEnum: GitVersionType | undefined;
      if (args.versionType && args.version) {
        if (args.versionType === 'branch') {
          versionTypeEnum = GitVersionType.Branch;
        } else if (args.versionType === 'commit') {
          versionTypeEnum = GitVersionType.Commit;
        } else if (args.versionType === 'tag') {
          versionTypeEnum = GitVersionType.Tag;
        }
      }
    
      const result = await getFileContent(
        connection,
        args.projectId ?? defaultProject,
        args.repositoryId,
        args.path,
        versionTypeEnum !== undefined && args.version
          ? { versionType: versionTypeEnum, version: args.version }
          : undefined,
      );
      return {
        content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
      };
    }
  • Type definition for the return value of getFileContent, indicating content and whether it's a directory.
    export interface FileContentResponse {
      content: string;
      isDirectory: boolean;
    }

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