Skip to main content
Glama

Flipt MCP Server

Official
by flipt-io
fliptClient.ts18.4 kB
import * as dotenv from 'dotenv'; // Import from the generated API import { BearerAuthAuthentication, createConfiguration } from '../generated/api/index'; import { ServerConfiguration } from '../generated/api/servers'; import { FlagsServiceApi, NamespacesServiceApi, SegmentsServiceApi, RulesServiceApi, RolloutsServiceApi, VariantsServiceApi, ConstraintsServiceApi, DistributionsServiceApi, EvaluationServiceApi, } from '../generated/api/index'; import { CreateFlagRequestTypeEnum } from '../generated/api/models/CreateFlagRequest'; import { CreateSegmentRequestMatchTypeEnum } from '../generated/api/models/CreateSegmentRequest'; import { UpdateSegmentRequestMatchTypeEnum } from '../generated/api/models/UpdateSegmentRequest'; /** * FliptClient implementation using the generated API code */ export class FliptClient { private flagsApi: FlagsServiceApi; private namespacesApi: NamespacesServiceApi; private segmentsApi: SegmentsServiceApi; private rulesApi: RulesServiceApi; private rolloutsApi: RolloutsServiceApi; private variantsApi: VariantsServiceApi; private constraintsApi: ConstraintsServiceApi; private distributionsApi: DistributionsServiceApi; private evaluationApi: EvaluationServiceApi; private baseUrl: string; private apiKey: string | undefined; constructor() { // Load environment variables dotenv.config(); this.baseUrl = process.env.FLIPT_URL || 'http://localhost:8080'; this.apiKey = process.env.FLIPT_API_KEY || undefined; const serverConfig = new ServerConfiguration<{}>(this.baseUrl, {}); const config = createConfiguration({ baseServer: serverConfig, }); if (this.apiKey) { config.authMethods.default = new BearerAuthAuthentication({ getToken: () => Promise.resolve(this.apiKey as string), }); } this.flagsApi = new FlagsServiceApi(config); this.namespacesApi = new NamespacesServiceApi(config); this.segmentsApi = new SegmentsServiceApi(config); this.rulesApi = new RulesServiceApi(config); this.rolloutsApi = new RolloutsServiceApi(config); this.variantsApi = new VariantsServiceApi(config); this.constraintsApi = new ConstraintsServiceApi(config); this.distributionsApi = new DistributionsServiceApi(config); this.evaluationApi = new EvaluationServiceApi(config); } // Namespace methods async createNamespace(key: string, name: string, description?: string) { try { const response = await this.namespacesApi.createNamespace({ key, name, description, }); return response; } catch (error) { console.error('Error creating namespace:', error); throw error; } } async updateNamespace(key: string, name: string, description?: string) { try { const response = await this.namespacesApi.updateNamespace(key, { name, description, }); return response; } catch (error) { console.error('Error updating namespace:', error); throw error; } } async deleteNamespace(key: string) { try { await this.namespacesApi.deleteNamespace(key); return { success: true }; } catch (error) { console.error('Error deleting namespace:', error); throw error; } } async listNamespaces() { try { const response = await this.namespacesApi.listNamespaces(); // The response is a NamespaceList object, not a response with a data property if (response && response.namespaces) { return response.namespaces; } else { console.error('Unexpected response structure:', response); return []; } } catch (error) { console.error('Error getting namespaces:', error); return []; } } async getNamespace(key: string) { try { const response = await this.namespacesApi.getNamespace(key); return response; } catch (error) { console.error(`Error getting namespace ${key}:`, error); throw error; } } // Flag methods async createFlag( namespaceKey: string, key: string, name: string, description?: string, enabled?: boolean, type?: string ) { try { const flagType = type === 'VARIANT_FLAG_TYPE' ? CreateFlagRequestTypeEnum.VariantFlagType : CreateFlagRequestTypeEnum.BooleanFlagType; const response = await this.flagsApi.createFlag(namespaceKey, { key, name, description, enabled: enabled ?? true, type: flagType, }); return response; } catch (error) { console.error('Error creating flag:', error); throw error; } } async updateFlag( namespaceKey: string, key: string, name: string, description?: string, enabled?: boolean ) { try { const response = await this.flagsApi.updateFlag(namespaceKey, key, { name, description, enabled, }); return response; } catch (error) { console.error('Error updating flag:', error); throw error; } } async deleteFlag(namespaceKey: string, key: string) { try { await this.flagsApi.deleteFlag(namespaceKey, key); return { success: true }; } catch (error) { console.error('Error deleting flag:', error); throw error; } } async listFlags(namespaceKey: string) { try { const response = await this.flagsApi.listFlags(namespaceKey); if (response && response.flags) { return response.flags; } else { console.error('Unexpected response structure:', response); return []; } } catch (error) { console.error(`Error getting flags for namespace ${namespaceKey}:`, error); return []; } } async getFlag(namespaceKey: string, key: string) { try { const response = await this.flagsApi.getFlag(namespaceKey, key); return response; } catch (error) { console.error(`Error getting flag ${key} in namespace ${namespaceKey}:`, error); throw error; } } // Segment methods async createSegment( namespaceKey: string, key: string, name: string, description?: string, matchType?: string ) { try { const segmentMatchType = matchType === 'ALL_MATCH_TYPE' ? CreateSegmentRequestMatchTypeEnum.AllMatchType : CreateSegmentRequestMatchTypeEnum.AnyMatchType; const response = await this.segmentsApi.createSegment(namespaceKey, { key, name, description, matchType: segmentMatchType, }); return response; } catch (error) { console.error('Error creating segment:', error); throw error; } } async updateSegment( namespaceKey: string, key: string, name: string, description?: string, matchType?: string ) { try { const segmentMatchType = matchType === 'ALL_MATCH_TYPE' ? UpdateSegmentRequestMatchTypeEnum.AllMatchType : UpdateSegmentRequestMatchTypeEnum.AnyMatchType; const response = await this.segmentsApi.updateSegment(namespaceKey, key, { name, description, matchType: segmentMatchType, }); return response; } catch (error) { console.error('Error updating segment:', error); throw error; } } async deleteSegment(namespaceKey: string, key: string) { try { await this.segmentsApi.deleteSegment(namespaceKey, key); return { success: true }; } catch (error) { console.error('Error deleting segment:', error); throw error; } } async listSegments(namespaceKey: string) { try { const response = await this.segmentsApi.listSegments(namespaceKey); if (response && response.segments) { return response.segments; } else { console.error('Unexpected response structure:', response); return []; } } catch (error) { console.error(`Error getting segments for namespace ${namespaceKey}:`, error); return []; } } async getSegment(namespaceKey: string, key: string) { try { const response = await this.segmentsApi.getSegment(namespaceKey, key); return response; } catch (error) { console.error(`Error getting segment ${key} in namespace ${namespaceKey}:`, error); throw error; } } // Rule methods async createRule( namespaceKey: string, flagKey: string, segmentKey: string, rank?: number, segmentOperator?: string ) { try { const response = await this.rulesApi.createRule(namespaceKey, flagKey, { segmentKey, rank: rank || 1, segmentOperator: (segmentOperator as any) || 'OR_SEGMENT_OPERATOR', }); return response; } catch (error) { console.error('Error creating rule:', error); throw error; } } async updateRule( namespaceKey: string, flagKey: string, id: string, segmentKey?: string, segmentOperator?: string ) { try { const response = await this.rulesApi.updateRule(namespaceKey, flagKey, id, { id, segmentKey, segmentOperator: segmentOperator as any, }); return response; } catch (error) { console.error('Error updating rule:', error); throw error; } } async deleteRule(namespaceKey: string, flagKey: string, id: string) { try { await this.rulesApi.deleteRule(namespaceKey, flagKey, id); return { success: true }; } catch (error) { console.error('Error deleting rule:', error); throw error; } } async orderRules(namespaceKey: string, flagKey: string, ruleIds: string[]) { try { await this.rulesApi.orderRules(namespaceKey, flagKey, { ruleIds, }); return { success: true }; } catch (error) { console.error('Error ordering rules:', error); throw error; } } async listRules(namespaceKey: string, flagKey: string) { try { const response = await this.rulesApi.listRules(namespaceKey, flagKey); if (response && response.rules) { return response.rules; } else { console.error('Unexpected response structure:', response); return []; } } catch (error) { console.error(`Error getting rules for flag ${flagKey} in namespace ${namespaceKey}:`, error); return []; } } // Rollout methods async createRollout( namespaceKey: string, flagKey: string, rank: number, description?: string, segment?: any, threshold?: any ) { try { const response = await this.rolloutsApi.createRollout(namespaceKey, flagKey, { rank, description, segment, threshold, }); return response; } catch (error) { console.error('Error creating rollout:', error); throw error; } } async updateRollout( namespaceKey: string, flagKey: string, id: string, description?: string, segment?: any, threshold?: any ) { try { const response = await this.rolloutsApi.updateRollout(namespaceKey, flagKey, id, { id, description, segment, threshold, }); return response; } catch (error) { console.error('Error updating rollout:', error); throw error; } } async deleteRollout(namespaceKey: string, flagKey: string, id: string) { try { await this.rolloutsApi.deleteRollout(namespaceKey, flagKey, id); return { success: true }; } catch (error) { console.error('Error deleting rollout:', error); throw error; } } async orderRollouts(namespaceKey: string, flagKey: string, rolloutIds: string[]) { try { await this.rolloutsApi.orderRollouts(namespaceKey, flagKey, { rolloutIds, }); return { success: true }; } catch (error) { console.error('Error ordering rollouts:', error); throw error; } } async listRollouts(namespaceKey: string, flagKey: string) { try { const response = await this.rolloutsApi.listRollouts(namespaceKey, flagKey); // The RolloutList model has 'rules' property instead of 'rollouts' if (response && response.rules) { return response.rules; } else { console.error('Unexpected response structure:', response); return []; } } catch (error) { console.error( `Error getting rollouts for flag ${flagKey} in namespace ${namespaceKey}:`, error ); return []; } } // Constraint methods async createConstraint( namespaceKey: string, segmentKey: string, type: string, property: string, operator: string, value?: string, description?: string ) { try { const response = await this.constraintsApi.createConstraint(namespaceKey, segmentKey, { type: type as any, // Using 'any' to handle the enum conversion property, operator, value, description, }); return response; } catch (error) { console.error('Error creating constraint:', error); throw error; } } async updateConstraint( namespaceKey: string, segmentKey: string, id: string, type: string, property: string, operator: string, value?: string, description?: string ) { try { const response = await this.constraintsApi.updateConstraint(namespaceKey, segmentKey, id, { id, type: type as any, // Using 'any' to handle the enum conversion property, operator, value, description, }); return response; } catch (error) { console.error('Error updating constraint:', error); throw error; } } async deleteConstraint(namespaceKey: string, segmentKey: string, id: string) { try { await this.constraintsApi.deleteConstraint(namespaceKey, segmentKey, id); return { success: true }; } catch (error) { console.error('Error deleting constraint:', error); throw error; } } // Variant methods async createVariant( namespaceKey: string, flagKey: string, key: string, name?: string, description?: string, attachment?: string ) { try { const response = await this.variantsApi.createVariant(namespaceKey, flagKey, { key, name: name || key, description, attachment, }); return response; } catch (error) { console.error('Error creating variant:', error); throw error; } } async updateVariant( namespaceKey: string, flagKey: string, id: string, key: string, name?: string, description?: string, attachment?: string ) { try { const response = await this.variantsApi.updateVariant(namespaceKey, flagKey, id, { id, key, name: name || key, description, attachment, }); return response; } catch (error) { console.error('Error updating variant:', error); throw error; } } async deleteVariant(namespaceKey: string, flagKey: string, id: string) { try { await this.variantsApi.deleteVariant(namespaceKey, flagKey, id); return { success: true }; } catch (error) { console.error('Error deleting variant:', error); throw error; } } // Distribution methods async createDistribution( namespaceKey: string, flagKey: string, ruleId: string, variantId: string, rollout: number ) { try { const response = await this.distributionsApi.createDistribution( namespaceKey, flagKey, ruleId, { variantId, rollout, } ); return response; } catch (error) { console.error('Error creating distribution:', error); throw error; } } async updateDistribution( namespaceKey: string, flagKey: string, ruleId: string, id: string, variantId: string, rollout: number ) { try { const response = await this.distributionsApi.updateDistribution( namespaceKey, flagKey, ruleId, id, { id, variantId, rollout, } ); return response; } catch (error) { console.error('Error updating distribution:', error); throw error; } } async deleteDistribution(namespaceKey: string, flagKey: string, ruleId: string, id: string) { try { await this.distributionsApi.deleteDistribution(namespaceKey, flagKey, ruleId, id); return { success: true }; } catch (error) { console.error('Error deleting distribution:', error); throw error; } } // Evaluation methods async evaluateBoolean( namespaceKey: string, flagKey: string, entityId: string, context: Record<string, string> = {} ) { try { const response = await this.evaluationApi.evaluateBoolean({ namespaceKey, flagKey, entityId, context, }); return response; } catch (error) { console.error('Error evaluating boolean flag:', error); throw error; } } async evaluateVariant( namespaceKey: string, flagKey: string, entityId: string, context: Record<string, string> = {} ) { try { const response = await this.evaluationApi.evaluateVariant({ namespaceKey, flagKey, entityId, context, }); return response; } catch (error) { console.error('Error evaluating variant flag:', error); throw error; } } async evaluateBatch( requests: Array<{ namespaceKey: string; flagKey: string; entityId: string; context?: Record<string, string>; }> ) { try { const response = await this.evaluationApi.evaluateBatch({ requests: requests.map(req => ({ namespaceKey: req.namespaceKey, flagKey: req.flagKey, entityId: req.entityId, context: req.context || {}, })), }); return response; } catch (error) { console.error('Error evaluating batch:', error); throw error; } } // Utility methods getBaseUrl(): string { return this.baseUrl; } }

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/flipt-io/mcp-server-flipt'

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