Skip to main content
Glama

1MCP Server

serverDetailFormatter.ts13.2 kB
import { OFFICIAL_REGISTRY_KEY, OutputFormat, RegistryServer, ServerPackage, Transport, } from '@src/domains/registry/types.js'; import boxen from 'boxen'; import chalk from 'chalk'; import { formatDate, formatRelativeDate } from './commonFormatters.js'; /** * Format a server's details for display */ export function formatServerDetails(server: RegistryServer, format: OutputFormat = 'table'): string { switch (format) { case 'json': return JSON.stringify(server, null, 2); case 'detailed': return formatDetailedServer(server); case 'table': default: return formatTableServer(server); } } /** * Format server as table */ function formatTableServer(server: RegistryServer): string { const meta = server._meta[OFFICIAL_REGISTRY_KEY]; const basicInfo: Record<string, string> = { Name: server.name, Description: server.description, Status: server.status, Version: server.version, 'Repository URL': server.repository.url, 'Repository Source': server.repository.source, }; if (server.repository.subfolder) { basicInfo['Repository Subfolder'] = server.repository.subfolder; } const packages = server.packages || []; if (packages.length > 0) { basicInfo['Package Count'] = packages.length.toString(); basicInfo['Registry Types'] = packages .map((p) => p.registryType) .filter(Boolean) .join(', ') || 'unknown'; basicInfo['Transport Types'] = packages .map((p) => formatDetailTransport(p.transport)) .filter(Boolean) .join(', ') || 'stdio'; } const remotes = server.remotes || []; if (remotes.length > 0) { basicInfo['Remote Endpoints'] = remotes.length.toString(); basicInfo['Remote Types'] = remotes.map((r) => r.type).join(', '); } basicInfo['Published At'] = formatDate(meta.publishedAt); basicInfo['Updated At'] = formatDate(meta.updatedAt); basicInfo['Is Latest'] = meta.isLatest ? 'Yes' : 'No'; basicInfo['Registry ID'] = meta.serverId; let result = '\nServer Details:\n'; console.table([basicInfo]); // Add packages table if available if (packages.length > 0) { result += '\nPackages:\n'; const packageData = packages.map((pkg, index) => ({ Index: index + 1, 'Registry Type': pkg.registryType || 'unknown', Identifier: pkg.identifier, Version: pkg.version || server.version, Transport: formatDetailTransport(pkg.transport) || 'stdio', Runtime: pkg.runtimeHint || 'N/A', 'Env Vars': (pkg.environmentVariables?.length || 0) > 0 ? pkg.environmentVariables?.length : 'None', Args: (pkg.packageArguments?.length || 0) + (pkg.runtimeArguments?.length || 0) || 'None', })); console.table(packageData); } // Add environment variables table if available const allEnvVars = packages.flatMap((pkg) => pkg.environmentVariables || []); if (allEnvVars.length > 0) { result += '\nEnvironment Variables:\n'; const envVarData = allEnvVars.map((envVar, index) => ({ Index: index + 1, Name: envVar.value || 'ENV_VAR', Required: envVar.isRequired ? 'Yes' : 'No', Secret: envVar.isSecret ? 'Yes' : 'No', Default: envVar.default || 'N/A', Description: envVar.description || 'N/A', })); console.table(envVarData); } // Add arguments table if available const allArgs = packages.flatMap((pkg) => [ ...(pkg.packageArguments || []).map((arg) => ({ ...arg, type: 'Package' })), ...(pkg.runtimeArguments || []).map((arg) => ({ ...arg, type: 'Runtime' })), ]); if (allArgs.length > 0) { result += '\nArguments:\n'; const argData = allArgs.map((arg, index) => ({ Index: index + 1, Name: arg.name || 'arg', Type: arg.type || 'N/A', Required: arg.isRequired ? 'Yes' : 'No', Secret: arg.isSecret ? 'Yes' : 'No', Repeated: arg.isRepeated ? 'Yes' : 'No', Default: arg.default || 'N/A', Description: arg.description || 'N/A', })); console.table(argData); } // Add remotes table if available if (remotes.length > 0) { result += '\nRemote Endpoints:\n'; const remoteData = remotes.map((remote, index) => ({ Index: index + 1, Type: remote.type, URL: remote.url, Headers: (remote.headers?.length || 0) > 0 ? remote.headers?.length : 'None', })); console.table(remoteData); } return result; } /** * Format server with enhanced detailed display */ function formatDetailedServer(server: RegistryServer): string { const meta = server._meta[OFFICIAL_REGISTRY_KEY]; // Status badge with color const statusColor = server.status === 'active' ? 'green' : server.status === 'deprecated' ? 'yellow' : 'red'; const statusBadge = chalk[statusColor].bold(`● ${server.status.toUpperCase()}`); // Header with enhanced information const header = chalk.cyan.bold(server.name) + ' ' + chalk.gray(`(${server.version})`) + ' ' + statusBadge; // Description with enhanced formatting const description = chalk.white(server.description); // Enhanced basic info section const basicInfo = [ `${chalk.cyan('Repository:')} ${server.repository.url}`, `${chalk.cyan('Source:')} ${server.repository.source}`, server.repository.subfolder ? `${chalk.cyan('Subfolder:')} ${server.repository.subfolder}` : '', server.websiteUrl ? `${chalk.cyan('Website:')} ${server.websiteUrl}` : '', `${chalk.cyan('Published:')} ${formatRelativeDate(meta.publishedAt)}`, `${chalk.cyan('Updated:')} ${formatRelativeDate(meta.updatedAt)}`, `${chalk.cyan('Latest Version:')} ${meta.isLatest ? chalk.green('Yes') : chalk.yellow('No')}`, ] .filter(Boolean) .join('\n'); let content = `${header}\n\n${description}\n\n${basicInfo}`; // Enhanced packages section with installation instructions const packages = server.packages || []; if (packages.length > 0) { const packagesList = packages .map((pkg, index) => { const registryType = pkg.registryType || 'unknown'; const transport = formatDetailTransport(pkg.transport) || 'stdio'; const installCmd = generateInstallCommand(pkg, server.version); let packageDetails = ` ${index + 1}. ${chalk.yellow(registryType)} - ${pkg.identifier} ${chalk.gray(`(${transport})`)} ${chalk.gray(`Install: ${installCmd}`)}`; // Add runtime hint if available if (pkg.runtimeHint) { packageDetails += `\n ${chalk.blue('Runtime:')} ${pkg.runtimeHint}`; } // Add file hash if available if (pkg.fileSha256) { packageDetails += `\n ${chalk.magenta('SHA256:')} ${pkg.fileSha256.substring(0, 16)}...`; } return packageDetails; }) .join('\n'); content += `\n\n${chalk.cyan.bold('Packages:')} ${chalk.gray(`(${packages.length})`)} ${packagesList}`; // Add environment variables if any packages have them const allEnvVars = packages.flatMap((pkg) => pkg.environmentVariables || []); if (allEnvVars.length > 0) { const envVarsList = allEnvVars .map((envVar, index) => { const required = envVar.isRequired ? chalk.red('*') : ''; const secret = envVar.isSecret ? chalk.yellow('🔒') : ''; const defaultVal = envVar.default ? chalk.gray(` (default: ${envVar.default})`) : ''; const description = envVar.description ? ` - ${envVar.description}` : ''; return ` ${index + 1}. ${envVar.value || 'ENV_VAR'}${required}${secret}${defaultVal}${description}`; }) .join('\n'); content += `\n\n${chalk.cyan.bold('Environment Variables:')} ${chalk.gray(`(${allEnvVars.length})`)} ${envVarsList}`; } // Add package arguments if any packages have them const allPackageArgs = packages.flatMap((pkg) => pkg.packageArguments || []); const allRuntimeArgs = packages.flatMap((pkg) => pkg.runtimeArguments || []); if (allPackageArgs.length > 0) { const packageArgsList = allPackageArgs .map((arg, index) => { const required = arg.isRequired ? chalk.red('*') : ''; const secret = arg.isSecret ? chalk.yellow('🔒') : ''; const repeated = arg.isRepeated ? chalk.blue('[]') : ''; const defaultVal = arg.default ? chalk.gray(` (default: ${arg.default})`) : ''; const type = arg.type ? chalk.magenta(`<${arg.type}>`) : ''; const description = arg.description ? ` - ${arg.description}` : ''; return ` ${index + 1}. ${arg.name || 'arg'}${required}${secret}${repeated} ${type}${defaultVal}${description}`; }) .join('\n'); content += `\n\n${chalk.cyan.bold('Package Arguments:')} ${chalk.gray(`(${allPackageArgs.length})`)} ${packageArgsList}`; } if (allRuntimeArgs.length > 0) { const runtimeArgsList = allRuntimeArgs .map((arg, index) => { const required = arg.isRequired ? chalk.red('*') : ''; const secret = arg.isSecret ? chalk.yellow('🔒') : ''; const repeated = arg.isRepeated ? chalk.blue('[]') : ''; const defaultVal = arg.default ? chalk.gray(` (default: ${arg.default})`) : ''; const type = arg.type ? chalk.magenta(`<${arg.type}>`) : ''; const hint = arg.valueHint ? chalk.cyan(` (hint: ${arg.valueHint})`) : ''; const description = arg.description ? ` - ${arg.description}` : ''; return ` ${index + 1}. ${arg.name || 'arg'}${required}${secret}${repeated} ${type}${defaultVal}${hint}${description}`; }) .join('\n'); content += `\n\n${chalk.cyan.bold('Runtime Arguments:')} ${chalk.gray(`(${allRuntimeArgs.length})`)} ${runtimeArgsList}`; } } // Enhanced remotes section const remotes = server.remotes || []; if (remotes.length > 0) { const remotesList = remotes .map((remote, index) => { let remoteDetails = ` ${index + 1}. ${chalk.yellow(remote.type)} - ${remote.url}`; // Add headers if available if (remote.headers && remote.headers.length > 0) { const headersList = remote.headers .map((header) => { const description = header.description ? ` (${header.description})` : ''; const required = header.isRequired ? chalk.red('*') : ''; const secret = header.isSecret ? chalk.yellow('🔒') : ''; return ` ${header.value || 'header'}${required}${secret}${description}`; }) .join('\n'); remoteDetails += `\n ${chalk.cyan('Headers:')}\n${headersList}`; } return remoteDetails; }) .join('\n'); content += `\n\n${chalk.cyan.bold('Remote Endpoints:')} ${chalk.gray(`(${remotes.length})`)} ${remotesList}`; } // Enhanced registry and metadata info const metaInfo = [ `${chalk.cyan('Registry ID:')} ${meta.serverId}`, `${chalk.cyan('Version ID:')} ${meta.versionId}`, ].filter(Boolean); content += `\n\n${chalk.cyan.bold('Registry Information:')} ${metaInfo.join('\n ')}`; // MCP Usage Instructions section content += `\n\n${chalk.cyan.bold('MCP Usage Instructions:')} ${chalk.gray('• Add to your MCP client configuration')} ${chalk.gray('• Use with 1MCP proxy for multiple server management')} ${chalk.gray('• Check transport compatibility with your client')}`; // Additional package information if available const packageInfo = []; if (packages.length > 0) { const registryTypes = [...new Set(packages.map((p) => p.registryType).filter(Boolean))]; const transports = [...new Set(packages.map((p) => formatDetailTransport(p.transport)).filter(Boolean))]; if (registryTypes.length > 0) { packageInfo.push(`${chalk.cyan('Registry Types:')} ${registryTypes.join(', ')}`); } if (transports.length > 0) { packageInfo.push(`${chalk.cyan('Transport Types:')} ${transports.join(', ')}`); } } if (packageInfo.length > 0) { content += `\n\n${chalk.cyan.bold('Package Information:')} ${packageInfo.join('\n ')}`; } return boxen(content, { padding: 1, margin: 1, borderStyle: 'round', borderColor: 'cyan', }); } /** * Generate installation command based on package type */ function generateInstallCommand(pkg: ServerPackage, version: string): string { const registryType = pkg.registryType; const identifier = pkg.identifier; const pkgVersion = pkg.version || version; switch (registryType) { case 'npm': return `npm install ${identifier}@${pkgVersion}`; case 'pypi': return `pip install ${identifier}==${pkgVersion}`; case 'docker': return `docker pull ${identifier}:${pkgVersion}`; default: return `${registryType}: ${identifier}@${pkgVersion}`; } } /** * Format transport value to handle objects and undefined values for detailed display */ function formatDetailTransport(transport?: Transport): string { if (!transport) return ''; if (typeof transport === 'string') return transport; if (typeof transport === 'object') { // Handle case where transport is an object return transport.type || String(transport); } return String(transport); }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/1mcp-app/agent'

If you have feedback or need assistance with the MCP directory API, please join our Discord server