UNPKG

@jwalsh/mcp-server-qrcode

Version:

Model Context Protocol server for generating QR codes

105 lines (104 loc) 3.94 kB
/** * QR Code Generator Core Functionality * * This module provides QR code generation capabilities that can be used * by both the CLI interface and MCP server implementation. */ import * as qrcode from 'qrcode'; import { exec } from 'child_process'; import { promisify } from 'util'; import { readFile } from 'fs/promises'; import { tmpdir } from 'os'; import { join } from 'path'; import { randomUUID } from 'crypto'; const execAsync = promisify(exec); /** * Generate a QR code with various output formats */ export async function generateQRCode(options) { const { content, size = 200, errorCorrectionLevel = 'M', format = 'dataURL' } = options; if (!content) { throw new Error('Content is required for QR code generation'); } if (size < 100 || size > 1000) { throw new Error('QR code size must be between 100 and 1000 pixels'); } try { // Different output formats if (format === 'dataURL') { // Generate QR code as data URL (base64 image) const dataUrl = await qrcode.toDataURL(content, { width: size, errorCorrectionLevel, }); return { content, format: 'dataURL', data: dataUrl, mimeType: 'image/png', }; } else if (format === 'utf8' || format === 'terminal') { // Generate QR code as UTF8 text try { // Try to use system qrencode for best terminal output const sizeOption = Math.max(1, Math.floor(size / 100)); // Convert pixel size to qrencode size (1-10) const { stdout } = await execAsync(`qrencode -o - -t UTF8 -l ${errorCorrectionLevel} -s ${sizeOption} '${content.replace(/'/g, "'\\''")}'`); return { content, format: 'terminal', data: stdout, }; } catch (err) { // Fallback to qrcode library if qrencode not available const qrCodeText = await qrcode.toString(content, { type: format === 'terminal' ? 'terminal' : 'utf8', errorCorrectionLevel, }); return { content, format: format, data: qrCodeText, }; } } else if (format === 'png' || format === 'base64') { // For MCP server - generate QR code as PNG and return as base64 const tempFilePath = join(tmpdir(), `qrcode-${randomUUID()}.png`); try { // Try using qrencode first (better quality) const sizeOption = Math.max(1, Math.floor(size / 100)); await execAsync(`qrencode -o "${tempFilePath}" -l ${errorCorrectionLevel} -s ${sizeOption} '${content.replace(/'/g, "'\\''")}'`); } catch (err) { // Fallback to qrcode library await qrcode.toFile(tempFilePath, content, { width: size, errorCorrectionLevel, }); } // Read the file as buffer and encode as base64 const imageBuffer = await readFile(tempFilePath); const base64Image = imageBuffer.toString('base64'); return { content, format: 'base64', data: base64Image, mimeType: 'image/png', }; } else { throw new Error(`Unsupported format: ${format}`); } } catch (error) { throw new Error(`QR code generation failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Validate QR code input content */ export function validateQRCodeInput(content) { return content.trim().length > 0; }