Skip to main content
Glama

mcp-github-project-manager

BaseGitHubRepository.ts3.7 kB
import { Octokit } from "@octokit/rest"; import { GitHubError, OctokitInstance } from "../types"; import { GitHubErrorHandler } from "../GitHubErrorHandler"; import { GitHubConfig } from "../config"; import { Resource, ResourceStatus } from "../../../domain/resource-types"; export interface IGitHubRepository { readonly octokit: OctokitInstance; readonly config: GitHubConfig; } export abstract class BaseGitHubRepository implements IGitHubRepository { private readonly errorHandler: GitHubErrorHandler; protected readonly retryAttempts: number = 3; constructor( public readonly octokit: OctokitInstance, public readonly config: GitHubConfig ) { this.errorHandler = new GitHubErrorHandler(); } protected get owner(): string { return this.config.owner; } protected get repo(): string { return this.config.repo; } protected get token(): string { return this.config.token; } protected async withRetry<T>( operation: () => Promise<T>, context?: string ): Promise<T> { let lastError: unknown; let error: unknown; for (let attempt = 0; attempt < this.retryAttempts; attempt++) { try { return await operation(); } catch (e) { error = e; lastError = e; const isRetryable = this.errorHandler.isRetryableError(error); const isLastAttempt = attempt === this.retryAttempts - 1; if (!isRetryable || isLastAttempt) { throw this.errorHandler.handleError( error, isLastAttempt ? `${context} (max retries exceeded)` : context ); } const headers = (error as GitHubError)?.response?.headers || {}; const delay = this.errorHandler.calculateRetryDelay(headers); await new Promise(resolve => setTimeout(resolve, delay)); } } throw this.errorHandler.handleError(lastError, context); } protected async graphql<T>( query: string, variables: Record<string, unknown> = {} ): Promise<T> { return this.withRetry( () => this.octokit.graphql<T>(query, { ...variables, owner: this.owner, repo: this.repo, }), 'executing GraphQL query' ); } protected async rest<T>( operation: (params: any) => Promise<{ data: T }>, params?: Record<string, unknown> ): Promise<T> { const result = await this.withRetry( () => operation(this.getRequestParams(params)), 'executing REST API call' ); return result.data; } protected getRequestParams<T extends Record<string, unknown>>( params?: Partial<T> ): T & { owner: string; repo: string } { return { owner: this.owner, repo: this.repo, ...params, } as T & { owner: string; repo: string }; } protected toISOString(date: string | Date): string { if (date instanceof Date) { return date.toISOString(); } return new Date(date).toISOString(); } protected parseDate(date: string | null | undefined): string | undefined { if (!date) return undefined; return new Date(date).toISOString(); } protected convertGitHubStatus(githubStatus: "open" | "closed"): ResourceStatus { return githubStatus === "open" ? ResourceStatus.ACTIVE : ResourceStatus.CLOSED; } protected convertToGitHubStatus(status: ResourceStatus): "open" | "closed" { switch (status) { case ResourceStatus.ACTIVE: case ResourceStatus.PLANNED: return "open"; case ResourceStatus.CLOSED: case ResourceStatus.COMPLETED: case ResourceStatus.ARCHIVED: case ResourceStatus.DELETED: return "closed"; default: return "closed"; } } }

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/kunwarVivek/mcp-github-project-manager'

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