Skip to main content
Glama
path-resolver.ts3.54 kB
import { execSync } from 'child_process'; import { createHash } from 'crypto'; import { homedir } from 'os'; import { resolve, join } from 'path'; import { existsSync } from 'fs'; /** * Get XDG Base Directory paths following XDG Base Directory Specification * @see https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html */ export function getXDGDataHome(): string { return process.env.XDG_DATA_HOME || join(homedir(), '.local', 'share'); } export function getXDGConfigHome(): string { return process.env.XDG_CONFIG_HOME || join(homedir(), '.config'); } export function getXDGCacheHome(): string { return process.env.XDG_CACHE_HOME || join(homedir(), '.cache'); } /** * Get the root directory for MCP backlog data * Priority: * 1. MCP_BACKLOG_DIR environment variable (for custom locations) * 2. XDG_DATA_HOME/mcp-backlog (XDG-compliant default) * 3. Current working directory .agent (legacy fallback) */ export function getBacklogRootDir(): string { // Allow override via environment variable if (process.env.MCP_BACKLOG_DIR) { return resolve(process.env.MCP_BACKLOG_DIR); } // Use XDG-compliant directory by default const xdgDataHome = getXDGDataHome(); return join(xdgDataHome, 'mcp-backlog'); } /** * Get project identifier for multi-project isolation * Uses git repository root if available, otherwise creates hash from cwd */ export function getProjectIdentifier(): string { try { // Try to get git root directory const gitRoot = execSync('git rev-parse --show-toplevel', { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'], }).trim(); // Use the basename of the git root as identifier const parts = gitRoot.split('/'); return parts[parts.length - 1] || 'default'; } catch (error) { // Not a git repository, use hash of current working directory const cwd = process.cwd(); const hash = createHash('sha256').update(cwd).digest('hex').substring(0, 8); // Combine basename with hash for readability const parts = cwd.split('/'); const basename = parts[parts.length - 1] || 'project'; return `${basename}-${hash}`; } } /** * Get the project-specific backlog directory */ export function getProjectBacklogDir(): string { const rootDir = getBacklogRootDir(); const projectId = getProjectIdentifier(); return join(rootDir, 'projects', projectId); } /** * Resolve a path within the backlog directory structure * @param paths Path segments to join * @returns Absolute path */ export function resolveBacklogPath(...paths: string[]): string { const projectDir = getProjectBacklogDir(); return join(projectDir, ...paths); } /** * Get the active backlog items directory */ export function getBacklogDir(): string { return resolveBacklogPath('Backlog'); } /** * Get the completed backlog items directory */ export function getCompletedBacklogDir(): string { return resolveBacklogPath('COMPLETED_Backlog'); } /** * Get environment information for debugging */ export function getPathInfo(): { rootDir: string; projectId: string; projectDir: string; backlogDir: string; completedDir: string; isLegacy: boolean; } { const rootDir = getBacklogRootDir(); const projectId = getProjectIdentifier(); const projectDir = getProjectBacklogDir(); const legacyDir = join(process.cwd(), '.agent'); return { rootDir, projectId, projectDir, backlogDir: getBacklogDir(), completedDir: getCompletedBacklogDir(), isLegacy: rootDir === legacyDir, }; }

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/rwese/mcp-backlog'

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