Skip to main content
Glama

Memory MCP Server

by inchan
utils.ts5.19 kB
import type { LogEntry, LogLevel } from './types'; import type { Uid } from './schemas'; // UID 생성을 위한 카운터 (고유성 보장) let uidCounter = 0; /** * 현재 타임스탬프로 UID 생성 */ export function generateUid(): Uid { const now = new Date(); const year = now.getFullYear(); const month = (now.getMonth() + 1).toString().padStart(2, '0'); const day = now.getDate().toString().padStart(2, '0'); const hours = now.getHours().toString().padStart(2, '0'); const minutes = now.getMinutes().toString().padStart(2, '0'); const seconds = now.getSeconds().toString().padStart(2, '0'); // 밀리초 + 카운터로 고유성 보장 (999를 넘으면 리셋) const milliseconds = now.getMilliseconds(); uidCounter = (uidCounter + 1) % 1000; const uniqueId = (milliseconds * 1000 + uidCounter) .toString() .padStart(6, '0'); return `${year}${month}${day}T${hours}${minutes}${seconds}${uniqueId}Z` as Uid; } /** * 파일 경로를 정규화 */ export function normalizePath(filePath: string): string { return filePath.replace(/\\/g, '/').replace(/\/+/g, '/'); } /** * 파일 경로에서 확장자 제거 */ export function removeExtension(filePath: string): string { return filePath.replace(/\.[^/.]+$/, ''); } /** * Markdown 링크 파싱 ([[링크]], [텍스트](링크)) */ export function parseMarkdownLinks(content: string): string[] { const wikiLinks = Array.from(content.matchAll(/\[\[([^\]]+)\]\]/g)) .map(match => match[1]?.trim()) .filter((link): link is string => Boolean(link)); const mdLinks = Array.from(content.matchAll(/\[([^\]]+)\]\(([^)]+)\)/g)) .map(match => match[2]?.trim()) .filter((link): link is string => Boolean(link)); return [...new Set([...wikiLinks, ...mdLinks])]; } /** * 텍스트를 스니펫으로 변환 (검색 결과용) */ export function createSnippet( content: string, query: string, maxLength: number = 200 ): string { const queryRegex = new RegExp(query, 'gi'); const match = content.match(queryRegex); if (!match) { return ( content.slice(0, maxLength) + (content.length > maxLength ? '...' : '') ); } const matchIndex = content.search(queryRegex); const start = Math.max(0, matchIndex - maxLength / 2); const end = Math.min(content.length, start + maxLength); let snippet = content.slice(start, end); if (start > 0) snippet = '...' + snippet; if (end < content.length) snippet = snippet + '...'; return snippet; } /** * 민감정보 마스킹 (이메일, 전화번호 등) */ export function maskSensitiveInfo(text: string): string { return ( text // 이메일 마스킹 .replace( /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g, '***@***.***' ) // 전화번호 마스킹 (한국 형식) .replace(/\b\d{2,3}-\d{3,4}-\d{4}\b/g, '***-****-****') // 신용카드 번호 마스킹 .replace( /\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/g, '****-****-****-****' ) ); } /** * 구조적 로그 생성 */ export function createLogEntry( level: LogLevel, message: string, metadata?: Record<string, unknown>, component?: string, operation?: string ): LogEntry { return { timestamp: new Date().toISOString(), level, message, ...(metadata && { metadata }), ...(component && { component }), ...(operation && { operation }), }; } /** * 디바운스 함수 */ export function debounce<T extends (..._args: unknown[]) => unknown>( func: T, wait: number ): (..._args: Parameters<T>) => void { let timeoutId: NodeJS.Timeout | undefined; return (...funcArgs: Parameters<T>) => { clearTimeout(timeoutId); timeoutId = setTimeout(() => func(...funcArgs), wait); }; } /** * 파일 크기를 사람이 읽기 쉬운 형태로 변환 */ export function formatFileSize(bytes: number): string { const units = ['B', 'KB', 'MB', 'GB']; let size = bytes; let unitIndex = 0; while (size >= 1024 && unitIndex < units.length - 1) { size /= 1024; unitIndex++; } return `${size.toFixed(1)} ${units[unitIndex]}`; } /** * 간단한 로거 클래스 */ class Logger { private level: LogLevel = 'info'; setLevel(level: LogLevel): void { this.level = level; } private shouldLog(level: LogLevel): boolean { const levels: Record<LogLevel, number> = { debug: 0, info: 1, warn: 2, error: 3, }; return levels[level] >= levels[this.level]; } debug(message: string, ...args: unknown[]): void { if (this.shouldLog('debug')) { console.debug(`[DEBUG] ${message}`, ...args); } } info(message: string, ...args: unknown[]): void { if (this.shouldLog('info')) { console.info(`[INFO] ${message}`, ...args); } } warn(message: string, ...args: unknown[]): void { if (this.shouldLog('warn')) { console.warn(`[WARN] ${message}`, ...args); } } error(message: string, ...args: unknown[]): void { if (this.shouldLog('error')) { console.error(`[ERROR] ${message}`, ...args); } } } /** * 글로벌 로거 인스턴스 */ export const logger = new Logger();

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/inchan/memory-mcp'

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