UNPKG

parserator-mcp-server

Version:

Intelligent data parsing for AI agents via Model Context Protocol

311 lines 11.7 kB
/** * Real Parserator API Client for MCP Server * Uses the actual production Parserator SDK with the Architect-Extractor pattern */ export class ParseratorClient { config; sdk; // Will be dynamically imported constructor(config) { this.config = { baseUrl: 'https://app-5108296280.us-central1.run.app', timeout: 30000, ...config }; } async initializeSDK() { if (!this.sdk) { // Note: In production, we would import the actual Parserator SDK // For now, we'll use the REST API directly since we're in MCP context this.sdk = { baseUrl: this.config.baseUrl, apiKey: this.config.apiKey, headers: { 'Authorization': `Bearer ${this.config.apiKey}`, 'Content-Type': 'application/json', 'User-Agent': 'Parserator MCP Server v1.0.0' } }; } } async parseData(inputData, outputSchema, instructions) { await this.initializeSDK(); try { const requestBody = { inputData, outputSchema, instructions, options: { includeMetadata: true, validateOutput: true } }; const response = await fetch(`${this.config.baseUrl}/v1/parse`, { method: 'POST', headers: this.sdk.headers, body: JSON.stringify(requestBody) }); if (!response.ok) { const errorData = await response.json().catch(() => ({})); throw new Error(`API Error ${response.status}: ${errorData.message || response.statusText}`); } const result = await response.json(); if (!result.success) { return { success: false, error: result.error?.message || 'Parse operation failed', code: result.error?.code || 'PARSE_FAILED' }; } return { success: true, parsedData: result.parsedData, confidence: result.metadata?.confidence, tokensUsed: result.metadata?.tokensUsed, processingTime: result.metadata?.processingTimeMs, requestId: result.metadata?.requestId }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Unknown error', code: 'NETWORK_ERROR' }; } } async validateSchema(data, schema) { await this.initializeSDK(); try { // Use Parserator's validation endpoint const requestBody = { data, schema }; const response = await fetch(`${this.config.baseUrl}/v1/validate`, { method: 'POST', headers: this.sdk.headers, body: JSON.stringify(requestBody) }); if (!response.ok) { throw new Error(`Validation API Error: ${response.status}`); } const result = await response.json(); return { success: true, valid: result.valid, errors: result.errors || [], suggestions: result.suggestions || [] }; } catch (error) { // Fallback to basic validation const isValid = this.basicValidation(data, schema); return { success: true, valid: isValid, errors: isValid ? [] : ['Basic validation failed - structure mismatch'], suggestions: isValid ? [] : ['Check that all required fields are present and correctly typed'] }; } } async suggestSchema(sampleData) { await this.initializeSDK(); try { const requestBody = { sampleData: sampleData.substring(0, 2000) }; // Limit sample size const response = await fetch(`${this.config.baseUrl}/v1/suggest-schema`, { method: 'POST', headers: this.sdk.headers, body: JSON.stringify(requestBody) }); if (!response.ok) { throw new Error(`Schema suggestion API Error: ${response.status}`); } const result = await response.json(); return { success: true, suggestedSchema: result.suggestedSchema, confidence: result.confidence || 0.8, reasoning: result.reasoning || 'AI-generated schema based on data patterns' }; } catch (error) { // Fallback to pattern-based schema generation const suggestedSchema = this.generatePatternSchema(sampleData); return { success: true, suggestedSchema, confidence: 0.7, reasoning: 'Generated using pattern detection (fallback method)' }; } } basicValidation(data, schema) { if (!data || !schema) return false; const dataKeys = Object.keys(data); const schemaKeys = Object.keys(schema); // Check if all schema keys are present in data return schemaKeys.every(key => dataKeys.includes(key)); } generatePatternSchema(sampleData) { const schema = {}; // Email detection if (sampleData.match(/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/)) { schema.email = 'string'; } // Date detection if (sampleData.match(/\d{4}-\d{2}-\d{2}|\d{1,2}\/\d{1,2}\/\d{4}/)) { schema.date = 'string'; } // Phone detection if (sampleData.match(/\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/)) { schema.phone = 'string'; } // Money/price detection if (sampleData.match(/\$\d+(?:\.\d{2})?|\d+(?:\.\d{2})?\s*(?:USD|dollars?)/i)) { schema.amount = 'number'; } // Name detection if (sampleData.match(/\b[A-Z][a-z]+\s+[A-Z][a-z]+\b/)) { schema.name = 'string'; } // Address detection if (sampleData.match(/\d+\s+[A-Za-z\s]+(?:Street|St|Avenue|Ave|Road|Rd|Boulevard|Blvd)/i)) { schema.address = 'string'; } // URL detection if (sampleData.match(/https?:\/\/[^\s]+/)) { schema.url = 'string'; } // Default fields for any content schema.extractedText = 'string'; schema.category = 'string'; return schema; } async getUsageStats() { await this.initializeSDK(); try { const response = await fetch(`${this.config.baseUrl}/v1/account/usage`, { method: 'GET', headers: this.sdk.headers }); if (!response.ok) { throw new Error(`Usage API Error: ${response.status}`); } return await response.json(); } catch (error) { // Return minimal mock data if real API fails return { requestsThisMonth: 0, tokensUsedThisMonth: 0, quotaRemaining: 1000, lastUpdated: new Date().toISOString(), error: 'Unable to fetch real usage data' }; } } async getTemplates() { await this.initializeSDK(); try { const response = await fetch(`${this.config.baseUrl}/v1/templates`, { method: 'GET', headers: this.sdk.headers }); if (!response.ok) { throw new Error(`Templates API Error: ${response.status}`); } return await response.json(); } catch (error) { // Return production-ready templates as fallback return [ { id: 'email-processor', name: 'Email Processor', description: 'Extract structured data from emails using Architect-Extractor pattern', schema: { sender: 'string', subject: 'string', recipients: 'string_array', tasks: 'string_array', dates: 'string_array', priority: 'string', actionRequired: 'boolean', summary: 'string' }, useCase: 'ai-agents' }, { id: 'invoice-extractor', name: 'Invoice Extractor', description: 'Parse invoices and receipts with high accuracy', schema: { vendor: 'string', vendorAddress: 'string', amount: 'number', tax: 'number', date: 'string', invoiceNumber: 'string', items: 'array', currency: 'string' }, useCase: 'business-automation' }, { id: 'contact-parser', name: 'Contact Parser', description: 'Extract contact information from various sources', schema: { name: 'string', title: 'string', company: 'string', email: 'string', phone: 'string', address: 'string', linkedin: 'string', notes: 'string' }, useCase: 'crm-integration' }, { id: 'document-analyzer', name: 'Document Analyzer', description: 'Analyze and extract key information from documents', schema: { documentType: 'string', title: 'string', author: 'string', date: 'string', keyPoints: 'string_array', summary: 'string', entities: 'array', sentiment: 'string' }, useCase: 'content-processing' } ]; } } async testConnection() { await this.initializeSDK(); const startTime = Date.now(); try { const response = await fetch(`${this.config.baseUrl}/health`, { method: 'GET', headers: { 'Authorization': this.sdk.headers.Authorization } }); const latency = Date.now() - startTime; return { success: response.ok, latency, error: response.ok ? undefined : `HTTP ${response.status}: ${response.statusText}` }; } catch (error) { return { success: false, latency: Date.now() - startTime, error: error instanceof Error ? error.message : 'Connection failed' }; } } } //# sourceMappingURL=parserator-client.js.map