Skip to main content
Glama
sources.ts3.98 kB
import { Request, Response } from "express"; import { ConnectorManager } from "../connectors/manager.js"; import { getDatabaseTypeFromDSN } from "../utils/dsn-obfuscate.js"; import { getToolsForSource } from "../utils/tool-metadata.js"; import type { SourceConfig } from "../types/config.js"; import type { components } from "./openapi.js"; type DataSource = components["schemas"]["DataSource"]; type SSHTunnel = components["schemas"]["SSHTunnel"]; type ErrorResponse = components["schemas"]["Error"]; /** * Transform a SourceConfig into an API DataSource response * Excludes sensitive fields like passwords and SSH credentials */ function transformSourceConfig( source: SourceConfig, isDefault: boolean ): DataSource { // Determine type from explicit config or infer from DSN if (!source.type && source.dsn) { const inferredType = getDatabaseTypeFromDSN(source.dsn); if (inferredType) { source.type = inferredType; } } if (!source.type) { throw new Error(`Source ${source.id} is missing required type field`); } const dataSource: DataSource = { id: source.id, type: source.type, is_default: isDefault, }; // Add connection details (excluding password) if (source.host) { dataSource.host = source.host; } if (source.port !== undefined) { dataSource.port = source.port; } if (source.database) { dataSource.database = source.database; } if (source.user) { dataSource.user = source.user; } // Add execution options if (source.readonly !== undefined) { dataSource.readonly = source.readonly; } if (source.max_rows !== undefined) { dataSource.max_rows = source.max_rows; } // Add SSH tunnel configuration (excluding credentials) if (source.ssh_host) { const sshTunnel: SSHTunnel = { enabled: true, ssh_host: source.ssh_host, }; if (source.ssh_port !== undefined) { sshTunnel.ssh_port = source.ssh_port; } if (source.ssh_user) { sshTunnel.ssh_user = source.ssh_user; } dataSource.ssh_tunnel = sshTunnel; } // Add tools for this source dataSource.tools = getToolsForSource(source.id); return dataSource; } /** * GET /api/sources * List all data sources */ export function listSources(req: Request, res: Response): void { try { const sourceConfigs = ConnectorManager.getAllSourceConfigs(); // Transform configs to API response format const sources: DataSource[] = sourceConfigs.map((config, index) => { const isDefault = index === 0; // First source is default return transformSourceConfig(config, isDefault); }); res.json(sources); } catch (error) { console.error("Error listing sources:", error); const errorResponse: ErrorResponse = { error: error instanceof Error ? error.message : "Internal server error", }; res.status(500).json(errorResponse); } } /** * GET /api/sources/:sourceId * Get a specific data source by ID */ export function getSource(req: Request, res: Response): void { try { const sourceId = req.params.sourceId; const sourceIds = ConnectorManager.getAvailableSourceIds(); // Get source config - will be null if source doesn't exist const sourceConfig = ConnectorManager.getSourceConfig(sourceId); if (!sourceConfig) { const errorResponse: ErrorResponse = { error: "Source not found", source_id: sourceId, }; res.status(404).json(errorResponse); return; } // Check if this is the default source const isDefault = sourceIds[0] === sourceId; // Transform and return const dataSource = transformSourceConfig(sourceConfig, isDefault); res.json(dataSource); } catch (error) { console.error(`Error getting source ${req.params.sourceId}:`, error); const errorResponse: ErrorResponse = { error: error instanceof Error ? error.message : "Internal server error", }; res.status(500).json(errorResponse); } }

Latest Blog Posts

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/bytebase/dbhub'

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