Skip to main content
Glama

Superglue MCP

Official
by superglue-ai
telemetry.ts4.85 kB
import { PostHog } from 'posthog-node'; import { server_defaults } from '../default.js'; import { logMessage } from "./logs.js"; // we use a privacy-preserving session id to track queries export const sessionId = crypto.randomUUID(); export const isDebug = process.env.DEBUG === "true"; export const isSelfHosted = process.env.RUNS_ON_SUPERGLUE_CLOUD !== "true"; export const isTelemetryDisabled = process.env.DISABLE_TELEMETRY === "true"; export const telemetryClient = !isTelemetryDisabled && !isDebug ? new PostHog( server_defaults.posthog.apiKey, { host: server_defaults.posthog.host, enableExceptionAutocapture: true } ) : null; if (telemetryClient) { logMessage('info', "superglue uses telemetry to understand how many users are using the platform. See self-hosting guide for more info."); } // Precompile the regex for better performance const OPERATION_REGEX = /(?:query|mutation|subscription)\s+(\w+)/; export const extractOperationName = (query: string): string => { if (!query) return 'unknown_query'; const match = OPERATION_REGEX.exec(query); return match?.[1] || 'unknown_query'; }; export const telemetryMiddleware = (req: any, res: any, next: any) => { if (!req?.body?.query || req.body.query.includes("IntrospectionQuery") || req.body.query.includes("__schema")) { return next(); } const operation = extractOperationName(req.body.query); logMessage('debug', `Executing ${operation}`, { orgId: req.orgId }); telemetryClient?.capture({ distinctId: req.orgId || sessionId, event: operation, properties: { query: req.body.query, orgId: req.orgId, } }); next(); }; const createCallProperties = (query: string, responseBody: any, isSelfHosted: boolean, operation: string) => { const properties: Record<string, any> = {}; properties.isSelfHosted = isSelfHosted; properties.operation = operation; properties.query = query; switch (operation) { case 'call': const call = responseBody?.singleResult?.data?.call; if (!call) break; properties.endpointHost = call?.config?.urlHost; properties.endpointPath = call?.config?.urlPath; properties.apiConfigId = call?.config?.id; properties.callMethod = call?.config?.method; properties.documentationUrl = call?.config?.documentationUrl; properties.authType = call?.config?.authentication; properties.responseTimeMs = call?.completedAt?.getTime() - call?.startedAt?.getTime() break; default: break; } return properties; } export const handleQueryError = (errors: any[], query: string, orgId: string, requestContext: any) => { // in case of an error, we track the query and the error // we do not track the variables or the response // all errors are masked const operation = extractOperationName(query); const properties = createCallProperties(query, requestContext.response?.body, isSelfHosted, operation); properties.success = false; logMessage('warn', `${operation} failed.\n${errors.map(e => `\n- ${e.message || e}`).join('\n')}`, { orgId: orgId }); telemetryClient?.capture({ distinctId: orgId || sessionId, event: operation + '_error', properties: { ...properties, orgId: orgId, errors: errors.map(e => ({ message: e.message, path: e.path })), success: false }, groups: { orgId: orgId } }); }; const handleQuerySuccess = (query: string, orgId: string, requestContext: any) => { if (!query || query.includes("IntrospectionQuery") || query.includes("__schema")) { return; } const distinctId = isSelfHosted ? `sh-inst-${requestContext.contextValue.datastore.storage?.tenant?.email}` : orgId; const operation = extractOperationName(query); const properties = createCallProperties(query, requestContext.response?.body, isSelfHosted, operation); properties.success = true; logMessage('debug', `${operation} successful`, { orgId: orgId }); telemetryClient?.capture({ distinctId: distinctId, event: operation, properties: properties, groups: { orgId: orgId } }); }; export const createTelemetryPlugin = () => { return { requestDidStart: async () => ({ willSendResponse: async (requestContext: any) => { const errors = requestContext.errors || requestContext?.response?.body?.singleResult?.errors || Object.values(requestContext?.response?.body?.singleResult?.data || {}).map((d: any) => d.error).filter(Boolean); const orgId = requestContext.contextValue.orgId; if (errors && errors.length > 0) { handleQueryError(errors, requestContext.request.query, orgId, requestContext); } else { handleQuerySuccess(requestContext.request.query, orgId, requestContext); } } }) }; };

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