Skip to main content
Glama
mednabouli

MCP Multi-Context Hook Generator

by mednabouli
api.ts3.31 kB
import fs from 'fs'; import path from 'path'; import { Project, TypeFormatFlags } from 'ts-morph'; let cachedProject: Project | null = null; export function getTsMorphProject(rootPath: string): Project { if (cachedProject) return cachedProject; // Ensure .cache/ts-morph exists const cacheDir = path.join(rootPath, '.cache', 'ts-morph'); if (!fs.existsSync(cacheDir)) fs.mkdirSync(cacheDir, { recursive: true }); // Create ts-morph Project with cache directory cachedProject = new Project({ tsConfigFilePath: path.join(rootPath, 'tsconfig.json'), skipAddingFilesFromTsConfig: true, manipulationSettings: { // Optional: speed up large projects usePrefixAndSuffixTextForRename: true, }, }); return cachedProject; } export interface ApiRoute { name: any; path: string; methods: string[]; responseType: string; kind: 'next-route' | 'api-client' | 'graphql-query' | 'graphql-mutation'; gqlString?: string; environment?: 'server' | 'client' | 'universal'; } // --------------------------------- // Detect environment from function body // --------------------------------- export function detectEnvironment(fnBody: string): 'server' | 'client' | 'universal' { if (/process\.env|prisma|fs|secret/i.test(fnBody)) return 'server'; // server-only if (/fetch|axios|gql/i.test(fnBody)) return 'client'; // client-only return 'universal'; // could run both } // --------------------------------- // Crawl API routes // --------------------------------- export function crawlApi(rootPath: string): ApiRoute[] { const results: ApiRoute[] = []; const clientApiDir = path.join(rootPath, 'api'); if (!fs.existsSync(clientApiDir)) return results; const files = fs.readdirSync(clientApiDir).filter((f: string) => f.endsWith('.ts')); const project = getTsMorphProject(rootPath); files.forEach((file: string) => { const filePath = path.join(clientApiDir, file); const sourceFile = project.addSourceFileAtPath(filePath); sourceFile.getFunctions().forEach((fn) => { if (!fn.isExported()) return; const fnName = fn.getName() || 'anonymous'; const sig = fn.getSignature(); // --- Fix for deprecated getText() --- const responseType = sig.getReturnType().getText(undefined, TypeFormatFlags.NoTruncation); const bodyText = fn.getBodyText() || ''; // Detect environment per function const environment = detectEnvironment(bodyText); // Detect GraphQL if (bodyText.includes('gql')) { const isMutation = bodyText.toLowerCase().includes('mutation'); // Extract gql string using regex const gqlMatch = bodyText.match(/gql`([\s\S]*?)`/); const gqlString = gqlMatch ? gqlMatch[1].trim() : undefined; results.push({ path: 'api/' + file, methods: [fnName], responseType, kind: isMutation ? 'graphql-mutation' : 'graphql-query', gqlString, environment, name: undefined, }); } else { // Regular API client results.push({ path: 'api/' + file, methods: [fnName], responseType, kind: 'api-client', environment, name: undefined, }); } }); }); return results; }

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/mednabouli/MCPV2'

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