Skip to main content
Glama
integration-setup.ts4.27 kB
import { Metadata } from "@playwright/test"; import { Integration } from "@superglue/client"; import { DataStore } from "../../../packages/core/datastore/types.js"; import { DocumentationFetcher } from "../../../packages/core/documentation/index.js"; import { logMessage } from "../../../packages/core/utils/logs.js"; import { replaceVariables } from "../../../packages/core/utils/helpers.js"; import type { AgentEvalConfig, IntegrationConfig } from "../types.js"; export class IntegrationSetupService { constructor( private datastore: DataStore, private config: AgentEvalConfig, private metadata: Metadata ) {} async setupIntegrations(): Promise<Integration[]> { const enabledTools = this.config.enabledTools === 'all' ? this.config.tools : this.config.tools.filter(tool => this.config.enabledTools.includes(tool.id)); const usedIntegrationIds = new Set( enabledTools.flatMap(tool => tool.integrationIds) ); const integrationConfigs = this.config.integrations.filter(integration => usedIntegrationIds.has(integration.id) ); this.applyEnvironmentVariablesToConfigs(integrationConfigs); const integrations = await Promise.all( integrationConfigs.map((config) => this.setupSingleIntegration(config)) ); logMessage("info", `${integrations.length}/${integrationConfigs.length} integrations setup complete`, this.metadata); return integrations; } private async setupSingleIntegration(integrationConfig: IntegrationConfig): Promise<Integration> { const existing = await this.datastore.getIntegration({ id: integrationConfig.id, includeDocs: true, orgId: this.metadata.orgId, }); if (existing) { logMessage("info", `${integrationConfig.name} already exists, skipping setup`, this.metadata); return { ...existing, credentials: integrationConfig.credentials, }; } const scopedCredentials = Object.entries(integrationConfig.credentials ?? {}).reduce( (acc, [key, value]) => { acc[`${integrationConfig.id}_${key}`] = value; return acc; }, {} as Record<string, string> ); const docFetcher = new DocumentationFetcher( { urlHost: await replaceVariables(integrationConfig.urlHost, scopedCredentials), urlPath: await replaceVariables(integrationConfig.urlPath, scopedCredentials), documentationUrl: await replaceVariables(integrationConfig.documentationUrl, scopedCredentials), openApiUrl: await replaceVariables(integrationConfig.openApiUrl, scopedCredentials), keywords: integrationConfig.keywords, }, scopedCredentials, this.metadata ); const docString = await docFetcher.fetchAndProcess(); await this.datastore.upsertIntegration({ id: integrationConfig.id, integration: { id: integrationConfig.id, name: integrationConfig.name, urlHost: integrationConfig.urlHost, urlPath: integrationConfig.urlPath, documentationUrl: integrationConfig.documentationUrl, documentation: docString, documentationPending: false, }, orgId: this.metadata.orgId, }); const finalIntegration = await this.datastore.getIntegration({ id: integrationConfig.id, includeDocs: true, orgId: this.metadata.orgId, }); if (!finalIntegration) { throw new Error(`Failed to get integration ${integrationConfig.name}`); } return { ...finalIntegration, credentials: integrationConfig.credentials, }; } private applyEnvironmentVariablesToConfigs(integrationConfigs: IntegrationConfig[]): void { for (const config of integrationConfigs) { if (!config.credentials || !config.id) { continue; } for (const [key, _] of Object.entries(config.credentials)) { const expectedEnvVarName = `${config.id.toUpperCase().replace(/-/g, '_')}_${key.toUpperCase()}`; const envValue = process.env[expectedEnvVarName]; if (envValue) { config.credentials[key] = envValue; } else { logMessage('warn', `Missing credential: ${config.id}.${key} (${expectedEnvVarName})`); } } } } }

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/superglue-ai/superglue'

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