Skip to main content
Glama
github.ts4.75 kB
// GitHub integration for fetching prompts import { Octokit } from '@octokit/rest'; import * as yaml from 'js-yaml'; import { GitHubConfig } from './config.js'; import { PromptInfo, PromptMetadata } from './types.js'; export class GitHubPromptFetcher { private octokit: Octokit; private config: GitHubConfig; constructor(config: GitHubConfig) { this.config = config; this.octokit = new Octokit({ auth: config.token, }); } /** * Fetch all prompts from the GitHub repository */ async fetchAllPrompts(): Promise<PromptInfo[]> { try { const params: any = { owner: this.config.owner, repo: this.config.repo, path: this.config.path || '', }; if (this.config.branch) { params.ref = this.config.branch; } const { data: contents } = await this.octokit.repos.getContent(params); if (!Array.isArray(contents)) { throw new Error('Expected directory listing but got file'); } const prompts: PromptInfo[] = []; // Filter for markdown files const markdownFiles = contents.filter( (file) => file.type === 'file' && file.name.endsWith('.md') ); // Fetch each prompt file for (const file of markdownFiles) { try { const prompt = await this.fetchPrompt(file.path); if (prompt) { prompts.push(prompt); } } catch (error) { console.error(`Error fetching prompt ${file.path}:`, error); } } return prompts; } catch (error) { console.error('Error fetching prompts from GitHub:', error); throw error; } } /** * Fetch a single prompt by path */ async fetchPrompt(path: string): Promise<PromptInfo | null> { try { const params: any = { owner: this.config.owner, repo: this.config.repo, path, }; if (this.config.branch) { params.ref = this.config.branch; } const { data } = await this.octokit.repos.getContent(params); if ('content' in data && data.type === 'file') { const content = Buffer.from(data.content, 'base64').toString('utf-8'); const promptInfo = this.parsePromptFile(content, path); return promptInfo; } return null; } catch (error) { console.error(`Error fetching prompt ${path}:`, error); return null; } } /** * Parse a prompt file with YAML frontmatter */ private parsePromptFile(content: string, path: string): PromptInfo { const frontmatterRegex = /^---\n([\s\S]*?)\n---\n([\s\S]*)$/; const match = content.match(frontmatterRegex); let metadata: PromptMetadata = { title: path.replace(/\.md$/, '').replace(/^.*\//, ''), description: '', category: 'general', tags: [], difficulty: 'intermediate', created: new Date().toISOString(), updated: new Date().toISOString(), }; let promptContent = content; if (match) { // Parse YAML frontmatter try { const yamlContent = match[1]; const parsedYaml = yaml.load(yamlContent || '') as any; // Map YAML fields to metadata if (parsedYaml.name) metadata.title = parsedYaml.name; if (parsedYaml.title) metadata.title = parsedYaml.title; if (parsedYaml.description) metadata.description = parsedYaml.description; if (parsedYaml.category) metadata.category = parsedYaml.category; if (parsedYaml.tags) metadata.tags = parsedYaml.tags; if (parsedYaml.difficulty) metadata.difficulty = parsedYaml.difficulty; if (parsedYaml.created) metadata.created = parsedYaml.created; if (parsedYaml.updated) metadata.updated = parsedYaml.updated; // Store arguments if present if (parsedYaml.arguments) { (metadata as any).arguments = parsedYaml.arguments; } promptContent = match[2]?.trim() || ''; } catch (error) { console.error('Error parsing YAML frontmatter:', error); } } return { name: metadata.title || 'Untitled', content: promptContent, metadata, }; } /** * Get repository information */ async getRepoInfo() { try { const { data } = await this.octokit.repos.get({ owner: this.config.owner, repo: this.config.repo, }); return data; } catch (error) { console.error('Error fetching repository info:', error); throw error; } } /** * Check if the repository is accessible */ async isAccessible(): Promise<boolean> { try { await this.getRepoInfo(); return true; } catch (error) { return false; } } }

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/jezweb/smart-prompts-mcp'

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