Skip to main content
Glama

faf_list

List directories and discover projects containing project.faf files to facilitate FAF discovery workflows.

Instructions

List directories and discover projects with project.faf files - Essential for FAF discovery workflow

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pathYesDirectory path to list (e.g., ~/Projects, /Users/username/Projects)
filterNoFilter: "faf" (only dirs with project.faf), "dirs" (all directories), "all" (dirs and files). Default: "dirs"
depthNoDirectory depth to scan: 1 (immediate children) or 2 (one level deeper). Default: 1
showHiddenNoShow hidden files/directories (starting with .). Default: false

Implementation Reference

  • The handleFafList method implements the logic for listing directories and identifying 'project.faf' files. It scans the provided path recursively up to a specified depth, filters results, and formats the output.
    private async handleFafList(args: any): Promise<CallToolResult> {
      try {
        const fs = await import('fs');
        const path = await import('path');
    
        // Parse arguments
        const targetPath = args?.path || this.engineAdapter.getWorkingDirectory();
        const filter = args?.filter || 'dirs';
        const depth = args?.depth || 1;
        const showHidden = args?.showHidden || false;
    
        // Expand tilde
        const expandedPath = targetPath.startsWith('~')
          ? path.join(require('os').homedir(), targetPath.slice(1))
          : targetPath;
    
        const resolvedPath = path.resolve(expandedPath);
    
        // Check if directory exists
        if (!fs.existsSync(resolvedPath)) {
          return {
            content: [{
              type: 'text',
              text: `❌ Directory not found: ${resolvedPath}`
            }],
            isError: true
          };
        }
    
        // Check if it's actually a directory
        const stats = fs.statSync(resolvedPath);
        if (!stats.isDirectory()) {
          return {
            content: [{
              type: 'text',
              text: `❌ Not a directory: ${resolvedPath}`
            }],
            isError: true
          };
        }
    
        // Scan directory
        const results: Array<{name: string; path: string; hasFaf: boolean; isDir: boolean}> = [];
    
        const scanDir = (dirPath: string, currentDepth: number) => {
          if (currentDepth > depth) return;
    
          const entries = fs.readdirSync(dirPath);
    
          for (const entry of entries) {
            // Skip hidden files unless requested
            if (!showHidden && entry.startsWith('.')) continue;
    
            const fullPath = path.join(dirPath, entry);
            const entryStats = fs.statSync(fullPath);
            const isDir = entryStats.isDirectory();
    
            // Check for project.faf
            const hasFaf = isDir && fs.existsSync(path.join(fullPath, 'project.faf'));
    
            // Apply filter
            if (filter === 'faf' && !hasFaf) continue;
            if (filter === 'dirs' && !isDir) continue;
    
            results.push({
              name: entry,
              path: fullPath,
              hasFaf,
              isDir
            });
    
            // Recurse if needed
            if (isDir && currentDepth < depth) {
              scanDir(fullPath, currentDepth + 1);
            }
          }
        };
    
        scanDir(resolvedPath, 1);
    
        // Sort: FAF projects first, then alphabetically
        results.sort((a, b) => {
          if (a.hasFaf && !b.hasFaf) return -1;
          if (!a.hasFaf && b.hasFaf) return 1;
          return a.name.localeCompare(b.name);
        });
    
        // Format output
        let output = `📁 ${resolvedPath}\n\n`;
    
        if (results.length === 0) {
          output += '(empty)\n';
        } else {
          for (const item of results) {
            const indent = item.path.split('/').length - resolvedPath.split('/').length - 1;
            const prefix = '  '.repeat(indent);
            const icon = item.isDir ? '📁' : '📄';
            const status = item.hasFaf ? '✅ project.faf' : '';
    
            output += `${prefix}${icon} ${item.name}`;
            if (status) output += ` ${status}`;
            output += '\n';
          }
        }
    
        output += `\nTotal: ${results.length} items`;
        if (filter === 'faf') {
          const fafCount = results.filter(r => r.hasFaf).length;
          output += ` (${fafCount} with project.faf)`;
        }
    
        return {
          content: [{
            type: 'text',
            text: output
          }]
        };
      } catch (error: unknown) {
        const errorMessage = error instanceof Error ? error.message : 'Unknown 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/Wolfe-Jam/grok-faf-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server