UNPKG

3gpp-mcp-server

Version:

MCP Server for querying 3GPP telecom protocol specifications

326 lines (303 loc) 11.6 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.GPPDocumentProcessor = void 0; const fs = __importStar(require("fs-extra")); const path = __importStar(require("path")); class GPPDocumentProcessor { constructor() { } async getDetailedSummary(filePath) { try { if (!await fs.pathExists(filePath)) { return this.generateMockDetailedSummary(filePath); } const content = await this.extractContent(filePath); return this.generateSummaryFromContent(content); } catch (error) { console.error(`Error processing document ${filePath}:`, error); return this.generateMockDetailedSummary(filePath); } } async getRawContent(filePath) { try { if (!await fs.pathExists(filePath)) { return this.generateMockRawContent(filePath); } return await this.extractContent(filePath); } catch (error) { console.error(`Error reading document ${filePath}:`, error); return `Error reading document: ${error instanceof Error ? error.message : 'Unknown error'}`; } } async extractDocumentChunks(filePath, chunkSize = 1000) { try { const content = await this.extractContent(filePath); return this.chunkText(content, chunkSize); } catch (error) { console.error(`Error chunking document ${filePath}:`, error); return []; } } async extractMetadata(filePath) { try { const content = await this.extractContent(filePath); return this.parseMetadata(content); } catch (error) { console.error(`Error extracting metadata from ${filePath}:`, error); return {}; } } async extractContent(filePath) { const ext = path.extname(filePath).toLowerCase(); switch (ext) { case '.md': return await fs.readFile(filePath, 'utf-8'); case '.docx': // In a real implementation, you would use a library like mammoth to extract DOCX content return `[DOCX Content from ${path.basename(filePath)}]\n\nThis is a placeholder for DOCX content. In a real implementation, this would be extracted using a library like mammoth.js`; default: throw new Error(`Unsupported file format: ${ext}`); } } generateSummaryFromContent(content) { // Extract key sections and create a summary const sections = this.extractSections(content); const keywords = this.extractKeywords(content); let summary = '# Document Summary\n\n'; if (sections.length > 0) { summary += '## Main Sections:\n'; sections.forEach((section, index) => { summary += `${index + 1}. ${section}\n`; }); summary += '\n'; } if (keywords.length > 0) { summary += `## Key Terms: ${keywords.slice(0, 10).join(', ')}\n\n`; } summary += '## Content Overview:\n'; summary += this.generateContentOverview(content); return Promise.resolve(summary); } extractSections(content) { const sections = []; const lines = content.split('\n'); for (const line of lines) { // Extract markdown headers const headerMatch = line.match(/^#+\s+(.+)$/); if (headerMatch) { sections.push(headerMatch[1].trim()); } } return sections.slice(0, 20); // Limit to first 20 sections } extractKeywords(content) { const keywords = new Set(); // Common 3GPP terms const gppTerms = [ 'NAS', 'RRC', 'PDCP', 'RLC', 'MAC', 'PHY', 'UE', 'eNB', 'gNB', 'MME', 'SGW', 'PGW', 'AMF', 'SMF', 'UPF', 'LTE', '5G', 'NR', 'EPS', 'IMS', 'Authentication', 'Security', 'Handover', 'Mobility', 'Bearer', 'QoS', 'Procedure', 'Protocol' ]; const lowercaseContent = content.toLowerCase(); for (const term of gppTerms) { if (lowercaseContent.includes(term.toLowerCase())) { keywords.add(term); } } // Extract capitalized words (likely technical terms) const capitalizedWords = content.match(/\b[A-Z]{2,}\b/g) || []; capitalizedWords.forEach(word => { if (word.length >= 3) { keywords.add(word); } }); return Array.from(keywords).slice(0, 20); } generateContentOverview(content) { const paragraphs = content .split('\n\n') .filter(p => p.trim().length > 100) .slice(0, 3); if (paragraphs.length === 0) { return 'No substantial content paragraphs found.'; } let overview = ''; paragraphs.forEach((paragraph, index) => { const cleaned = paragraph.replace(/#+\s*/, '').trim(); overview += `**Excerpt ${index + 1}:** ${cleaned.substring(0, 200)}...\n\n`; }); return overview; } chunkText(text, chunkSize) { const chunks = []; const sentences = text.split(/[.!?]+/); let currentChunk = ''; for (const sentence of sentences) { const trimmedSentence = sentence.trim(); if (!trimmedSentence) continue; if (currentChunk.length + trimmedSentence.length > chunkSize) { if (currentChunk) { chunks.push(currentChunk.trim()); currentChunk = trimmedSentence; } } else { currentChunk += (currentChunk ? '. ' : '') + trimmedSentence; } } if (currentChunk) { chunks.push(currentChunk.trim()); } return chunks; } parseMetadata(content) { const metadata = {}; // Extract title (first header) const titleMatch = content.match(/^#+\s+(.+)$/m); if (titleMatch) { metadata.title = titleMatch[1].trim(); } // Extract abstract (content after "Abstract" header) const abstractMatch = content.match(/#+\s*Abstract\s*\n+(.*?)(?=\n#+|\n\n|$)/si); if (abstractMatch) { metadata.abstract = abstractMatch[1].trim().substring(0, 500); } // Extract sections metadata.sections = this.extractSections(content); // Extract keywords metadata.keywords = this.extractKeywords(content); return metadata; } generateMockDetailedSummary(filePath) { const fileName = path.basename(filePath); const specMatch = fileName.match(/(\d{2})\.(\d{3})/); return `# Detailed Summary - ${fileName} ## Overview This is a mock detailed summary for ${fileName}. In a real implementation, this would contain: ## Key Sections 1. Scope and Purpose 2. References 3. Definitions and Abbreviations 4. General Requirements 5. Procedures and Protocols 6. Information Elements 7. Message Formats ## Technical Details - **Specification**: ${specMatch ? `TS ${specMatch[1]}.${specMatch[2]}` : 'Unknown'} - **Protocol Layer**: ${this.guessProtocolLayer(fileName)} - **Key Features**: ${this.guessKeyFeatures(fileName).join(', ')} ## Implementation Notes This document would typically include detailed procedural flows, message definitions, and technical requirements for implementation. *Note: This is a mock summary. Real implementation would parse actual document content.* `; } generateMockRawContent(filePath) { const fileName = path.basename(filePath); return `# ${fileName} - Raw Content This is mock raw content for demonstration purposes. ## 1. Scope This Technical Specification defines the procedures and protocols for [specific area based on filename]. ## 2. References [List of referenced specifications] ## 3. Definitions and Abbreviations ### 3.1 Definitions - Term 1: Definition 1 - Term 2: Definition 2 ### 3.2 Abbreviations - UE: User Equipment - eNB: evolved Node B - MME: Mobility Management Entity ## 4. General Description [Technical description content...] ## 5. Procedures ### 5.1 Procedure 1 [Detailed procedure steps...] ### 5.2 Procedure 2 [Detailed procedure steps...] ## 6. Information Elements [IE definitions...] ## 7. Message Formats [Message format definitions...] --- *Note: This is mock content. Real implementation would extract actual document text.* `; } guessProtocolLayer(fileName) { const name = fileName.toLowerCase(); if (name.includes('nas')) return 'Non-Access Stratum (NAS)'; if (name.includes('rrc')) return 'Radio Resource Control (RRC)'; if (name.includes('mac')) return 'Medium Access Control (MAC)'; if (name.includes('rlc')) return 'Radio Link Control (RLC)'; if (name.includes('pdcp')) return 'Packet Data Convergence Protocol (PDCP)'; if (name.includes('phy')) return 'Physical Layer (PHY)'; return 'Protocol Layer TBD'; } guessKeyFeatures(fileName) { const features = []; const name = fileName.toLowerCase(); if (name.includes('security')) features.push('Security'); if (name.includes('auth')) features.push('Authentication'); if (name.includes('mobility')) features.push('Mobility Management'); if (name.includes('session')) features.push('Session Management'); if (name.includes('bearer')) features.push('Bearer Management'); if (name.includes('qos')) features.push('Quality of Service'); if (name.includes('handover')) features.push('Handover'); if (name.includes('codec')) features.push('Audio/Video Codec'); return features.length > 0 ? features : ['General Protocol Procedures']; } } exports.GPPDocumentProcessor = GPPDocumentProcessor; //# sourceMappingURL=document-processor.js.map