Skip to main content
Glama

Bucket Feature Flags MCP Server

Official
by reflagcom
mcp.ts5.42 kB
import { select } from "@inquirer/prompts"; import chalk from "chalk"; import { Command } from "commander"; import { parse as parseJSON, stringify as stringifyJSON } from "comment-json"; import { mkdir, readFile, writeFile } from "node:fs/promises"; import { dirname, join, relative } from "node:path"; import ora, { type Ora } from "ora"; import { ConfigPaths, getServersConfig, resolveConfigPath, SupportedEditor, SupportedEditors, } from "../services/mcp.js"; import { configStore } from "../stores/config.js"; import { handleError } from "../utils/errors.js"; import { fileExists } from "../utils/file.js"; import { configScopeOption, editorOption } from "../utils/options.js"; export const mcpAction = async (options: { editor?: SupportedEditor; scope?: "local" | "global"; }) => { const config = configStore.getConfig(); let spinner: Ora | undefined; let selectedEditor = options.editor; // Select Editor/Client if (!selectedEditor) { selectedEditor = await select<SupportedEditor>({ message: "Which editor do you want to configure?", choices: SupportedEditors.map((value) => ({ value, name: ConfigPaths[value].name, })), }); } // Determine Config Path const projectPath = configStore.getProjectPath(); const globalPath = resolveConfigPath(selectedEditor, false); const localPath = resolveConfigPath(selectedEditor, true); const fullLocalPath = localPath ? join(projectPath, localPath) : undefined; if (!globalPath) { throw new Error(`Unsupported platform for editor: ${selectedEditor}`); } let configPathType: "global" | "local" = "global"; if (fullLocalPath) { if (options.scope) { configPathType = options.scope; } else { configPathType = await select<"global" | "local">({ message: "Configure global or project-local settings?", choices: [ { name: `Local (${relative(projectPath, fullLocalPath)})`, value: "local", }, { name: `Global (${globalPath})`, value: "global" }, ], }); } } const configPath = configPathType === "local" ? fullLocalPath! : globalPath; const displayConfigPath = configPathType === "local" ? relative(projectPath, configPath) : configPath; // Read/Parse Config File spinner = ora( `Reading configuration file: ${chalk.cyan(displayConfigPath)}...`, ).start(); let editorConfig: any = {}; if (await fileExists(configPath)) { const content = await readFile(configPath, "utf-8"); // Attempt to parse JSON, handle potential comments if needed try { editorConfig = parseJSON(content); } catch { spinner.fail( `Failed to parse configuration file ${chalk.cyan(displayConfigPath)}.`, ); } spinner.succeed( `Read configuration file ${chalk.cyan(displayConfigPath)}.`, ); } else { spinner.info("Configuration file not found, will create a new one."); editorConfig = {}; // Initialize empty config if file doesn't exist } // Ensure MCP servers object exists const serversConfig = getServersConfig( editorConfig, selectedEditor, configPathType, ); // Check for existing Reflag servers const existingReflagEntries = Object.keys(serversConfig).filter((key) => /reflag/i.test(key), ); // Prompt for Add/Update let targetEntryKey: string; const defaultNewKey = `Reflag`; if (existingReflagEntries.length === 0) { targetEntryKey = defaultNewKey; console.log(`Adding new MCP server entry: ${chalk.cyan(targetEntryKey)}`); } else { const choices = [ { name: `Add: ${defaultNewKey}`, value: "add_new" }, ...existingReflagEntries.map((key) => ({ name: `Update: ${key}`, value: key, })), ]; const choice = await select({ message: "Add a new MCP server or update an existing one?", choices, }); if (choice === "add_new") { targetEntryKey = defaultNewKey; console.log(`Adding new MCP server entry: ${chalk.cyan(targetEntryKey)}`); } else { targetEntryKey = choice; console.log( `Updating existing MCP server entry: ${chalk.cyan(targetEntryKey)}`, ); } } // Construct the MCP endpoint URL const newEntryValue = { url: config.apiUrl + "/mcp", }; // Update Config Object serversConfig[targetEntryKey] = newEntryValue; // Write Config File spinner = ora( `Writing configuration to ${chalk.cyan(displayConfigPath)}...`, ).start(); try { // Ensure the directory exists before writing await mkdir(dirname(configPath), { recursive: true }); const configString = stringifyJSON(editorConfig, null, 2); await writeFile(configPath, configString); spinner.succeed( `Configuration updated successfully in ${chalk.cyan(displayConfigPath)}.`, ); console.log( chalk.grey( "You may need to restart your editor for changes to take effect.", ), ); } catch (error) { spinner.fail( `Failed to write configuration file ${chalk.cyan(displayConfigPath)}.`, ); handleError(error, "MCP Configuration"); } }; export function registerMcpCommand(cli: Command) { cli .command("mcp") .description("Configure Reflag's remote MCP server for your AI assistant.") .addOption(editorOption) .addOption(configScopeOption) .action(mcpAction); }

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