3gpp-mcp-server
Version:
MCP Server for querying 3GPP telecom protocol specifications
326 lines (303 loc) • 11.6 kB
JavaScript
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
;