import { Constants } from 'librechat-data-provider'; export const mcpToolPattern = new RegExp(`^.+${Constants.mcp_delimiter}.+$`); /** * Normalizes a server name to match the pattern ^[a-zA-Z0-9_.-]+$ * This is required for Azure OpenAI models with Tool Calling */ export function normalizeServerName(serverName: string): string { // Check if the server name already matches the pattern if (/^[a-zA-Z0-9_.-]+$/.test(serverName)) { return serverName; } /** Replace non-matching characters with underscores. This preserves the general structure while ensuring compatibility. Trims leading/trailing underscores */ const normalized = serverName.replace(/[^a-zA-Z0-9_.-]/g, '_').replace(/^_+|_+$/g, ''); // If the result is empty (e.g., all characters were non-ASCII and got trimmed), // generate a fallback name to ensure we always have a valid function name if (!normalized) { /** Hash of the original name to ensure uniqueness */ let hash = 0; for (let i = 0; i < serverName.length; i++) { hash = (hash << 5) - hash + serverName.charCodeAt(i); hash |= 0; // Convert to 32bit integer } return `server_${Math.abs(hash)}`; } return normalized; } /** * Sanitizes a URL by removing query parameters to prevent credential leakage in logs. * @param url - The URL to sanitize (string or URL object) * @returns The sanitized URL string without query parameters */ export function sanitizeUrlForLogging(url: string | URL): string { try { const urlObj = typeof url === 'string' ? new URL(url) : url; return `${urlObj.protocol}//${urlObj.host}${urlObj.pathname}`; } catch { return '[invalid URL]'; } }