Skip to main content
Glama
cleanup.ts2.82 kB
#!/usr/bin/env node import { MCPTestClient } from './mcp-client'; function parseArgs(argv: string[]): { pattern: string; olderThanHours: number } { const args = argv.slice(2); let pattern = '^(E2E|MCP_E2E)'; let olderThanHours = 2; for (let i = 0; i < args.length; i++) { const a = args[i]; if (a === '--pattern' && i + 1 < args.length) pattern = args[++i] ?? pattern; else if ((a === '--older-than-hours' || a === '--hours') && i + 1 < args.length) { const next = args[++i] ?? String(olderThanHours); const parsed = parseInt(next, 10); olderThanHours = Number.isNaN(parsed) ? olderThanHours : parsed; } } return { pattern, olderThanHours }; } function extractTimestamp(str: string): number | null { const m = str.match(/(\d{13})$/); const ts = m?.[1]; if (typeof ts === 'string') return parseInt(ts, 10); return null; } /** * Safely create a RegExp from user input with validation. * Limits pattern length to prevent ReDoS attacks. */ function safeRegExp(pattern: string, maxLength = 200): RegExp { if (pattern.length > maxLength) { throw new Error(`Pattern too long (max ${maxLength} characters): ${pattern.slice(0, 50)}...`); } try { return new RegExp(pattern); } catch (e) { throw new Error(`Invalid regex pattern: ${e instanceof Error ? e.message : String(e)}`); } } async function main(): Promise<void> { const { pattern, olderThanHours } = parseArgs(process.argv); const now = Date.now(); const cutoff = now - olderThanHours * 3600 * 1000; const re = safeRegExp(pattern); const client = new MCPTestClient({ mode: 'full' }); await client.connect(); try { const list = await client.callTool('list_projects', { all: true, maxPages: 50 }); const items: Array<{ id?: string; name?: string }> = ( typeof list === 'object' && list !== null && 'items' in (list as Record<string, unknown>) ? (((list as { items?: unknown[] }).items as unknown[] | undefined) ?? []) : [] ) as Array<{ id?: string; name?: string }>; const targets = items.filter((p) => { const id = String(p.id ?? ''); const name = String(p.name ?? ''); if (!re.test(id) && !re.test(name)) return false; const ts = extractTimestamp(name) ?? extractTimestamp(id); return ts != null ? ts < cutoff : true; }); for (const p of targets) { const id = String(p.id ?? ''); if (!id) continue; try { const res = await client.callTool('delete_project', { projectId: id }); process.stdout.write(`Deleted project ${id}: ${JSON.stringify(res)}\n`); } catch (e) { process.stderr.write(`Failed to delete ${id}: ${String(e)}\n`); } } } finally { await client.close(); } } main().catch((e) => { console.error(e); process.exit(1); });

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/Daghis/teamcity-mcp'

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