Skip to main content
Glama

Bucket Feature Flags MCP Server

Official
by reflagcom
config.ts4.31 kB
import { readFileSync } from "fs"; import { version } from "../package.json"; import { LOG_LEVELS } from "./types"; import { isObject, ok } from "./utils"; export const API_BASE_URL = "https://front.reflag.com"; export const SDK_VERSION_HEADER_NAME = "reflag-sdk-version"; export const SDK_VERSION = `node-sdk/${version}`; export const API_TIMEOUT_MS = 10000; export const END_FLUSH_TIMEOUT_MS = 5000; export const REFLAG_LOG_PREFIX = "[Reflag]"; export const FLAG_EVENT_RATE_LIMITER_WINDOW_SIZE_MS = 60 * 1000; export const FLAGS_REFETCH_MS = 60 * 1000; // re-fetch every 60 seconds export const BATCH_MAX_SIZE = 100; export const BATCH_INTERVAL_MS = 10 * 1000; function parseOverrides(config: object | undefined) { if (!config) return {}; if ("flagOverrides" in config && isObject(config.flagOverrides)) { Object.entries(config.flagOverrides).forEach(([key, value]) => { ok( typeof value === "boolean" || isObject(value), `invalid type "${typeof value}" for key ${key}, expected boolean or object`, ); if (isObject(value)) { ok( "isEnabled" in value && typeof value.isEnabled === "boolean", `invalid type "${typeof value.isEnabled}" for key ${key}.isEnabled, expected boolean`, ); ok( value.config === undefined || isObject(value.config), `invalid type "${typeof value.config}" for key ${key}.config, expected object or undefined`, ); if (isObject(value.config)) { ok( "key" in value.config && typeof value.config.key === "string", `invalid type "${typeof value.config.key}" for key ${key}.config.key, expected string`, ); } } }); return config.flagOverrides; } return {}; } function loadConfigFile(file: string) { const configJson = readFileSync(file, "utf-8"); const config = JSON.parse(configJson); ok(typeof config === "object", "config must be an object"); const { secretKey, logLevel, offline, host, apiBaseUrl } = config; ok( typeof secretKey === "undefined" || typeof secretKey === "string", "secret must be a string", ); ok( typeof apiBaseUrl === "undefined" || typeof apiBaseUrl === "string", "apiBaseUrl must be a string", ); ok( typeof logLevel === "undefined" || (typeof logLevel === "string" && LOG_LEVELS.includes(logLevel as any)), `logLevel must one of ${LOG_LEVELS.join(", ")}`, ); ok( typeof offline === "undefined" || typeof offline === "boolean", "offline must be a boolean", ); return { flagOverrides: parseOverrides(config), secretKey, logLevel, offline, apiBaseUrl: host ?? apiBaseUrl, }; } function loadEnvVars() { const secretKey = process.env.REFLAG_SECRET_KEY; const enabledFlags = process.env.REFLAG_FLAGS_ENABLED; const disabledFlags = process.env.REFLAG_FLAGS_DISABLED; const logLevel = process.env.REFLAG_LOG_LEVEL; const apiBaseUrl = process.env.REFLAG_API_BASE_URL; const offline = process.env.REFLAG_OFFLINE !== undefined ? ["true", "on"].includes(process.env.REFLAG_OFFLINE) : undefined; let flagOverrides: Record<string, boolean> = {}; if (enabledFlags) { flagOverrides = enabledFlags.split(",").reduce( (acc, f) => { const key = f.trim(); if (key) acc[key] = true; return acc; }, {} as Record<string, boolean>, ); } if (disabledFlags) { flagOverrides = { ...flagOverrides, ...disabledFlags.split(",").reduce( (acc, f) => { const key = f.trim(); if (key) acc[key] = false; return acc; }, {} as Record<string, boolean>, ), }; } return { secretKey, flagOverrides, logLevel, offline, apiBaseUrl }; } export function loadConfig(file?: string) { let fileConfig; if (file) { fileConfig = loadConfigFile(file); } const envConfig = loadEnvVars(); return { secretKey: envConfig.secretKey || fileConfig?.secretKey, logLevel: envConfig.logLevel || fileConfig?.logLevel, offline: envConfig.offline ?? fileConfig?.offline, apiBaseUrl: envConfig.apiBaseUrl ?? fileConfig?.apiBaseUrl, flagOverrides: { ...fileConfig?.flagOverrides, ...envConfig.flagOverrides, }, }; }

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/reflagcom/bucket-javascript-sdk'

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