ffs_update_account
Update feature flag values for RingCentral accounts or extensions to control specific functionality settings.
Instructions
Update an AccountId or ExtensionId to use a specific Flag value. Uses MCP Auto Condition for management.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| flagId | Yes | Complete FFS Flag ID | |
| id | Yes | AccountId or ExtensionId to update | |
| targetValueId | Yes | Target Value ID from ffs_get_flag_options |
Implementation Reference
- src/index.ts:253-300 (handler)The main handler function for 'ffs_update_account' tool. It receives flagId, id, and targetValueId parameters, calls updateAccountValue helper, parses JSON values, and returns formatted success/error response.
async ({ flagId, id, targetValueId }) => { try { const result = await updateAccountValue(flagId, id, targetValueId); let currentParsed: unknown = result.currentValue; let previousParsed: unknown = result.previousValue; try { currentParsed = JSON.parse(result.currentValue); if (result.previousValue) { previousParsed = JSON.parse(result.previousValue); } } catch { // Keep as string } return { content: [ { type: 'text' as const, text: JSON.stringify({ success: true, flagId, id, previousValue: previousParsed, currentValue: currentParsed, targetValueId, message: result.previousValue ? `Successfully updated ID ${id} from ${JSON.stringify(previousParsed)} to ${JSON.stringify(currentParsed)}` : `Successfully set ID ${id} to ${JSON.stringify(currentParsed)}`, }, null, 2), }, ], }; } catch (error) { return { content: [ { type: 'text' as const, text: JSON.stringify({ success: false, message: error instanceof Error ? error.message : 'Unknown error', }, null, 2), }, ], isError: true, }; } } - src/ffs-service.ts:152-263 (helper)Core helper function updateAccountValue that implements the account update logic: retrieves flag config, finds target rule, tracks previous value, removes ID from existing conditions, adds to MCP Auto condition, reassigns priorities, and sends PUT request to update the flag.
export async function updateAccountValue( flagId: string, id: string, targetValueId: string ): Promise<{ success: boolean; previousValue: string | null; currentValue: string }> { // Step 1: Get current flag configuration const flag = await getFlag(flagId); const newFlag = JSON.parse(JSON.stringify(flag)) as FfsFlag; delete (newFlag as { creationTime?: string }).creationTime; // Step 2: Find target rule const targetRule = newFlag.rules.find((r) => r.value.id === targetValueId); if (!targetRule) { throw new Error(`Value ID not found: ${targetValueId}`); } // Step 3: Get previous value let previousValue: string | null = null; for (const rule of newFlag.rules) { for (const cond of rule.conditions) { if (cond.dimension === 'AccountId' && cond.argument?.split(',').includes(id)) { previousValue = rule.value.value; } } } // Step 4: Remove ID from all conditions for (const rule of newFlag.rules) { for (const cond of rule.conditions) { if (cond.dimension === 'AccountId' && cond.argument) { const accounts = cond.argument.split(','); if (accounts.includes(id)) { cond.argument = accounts.filter((a) => a !== id).join(','); } } } } // Step 5: Add to target MCP Auto condition const mcpConditionName = `${FFS_CONFIG.mcpAutoPrefix} [${targetValueId}]`; let mcpCondition = targetRule.conditions.find((c) => c.description?.startsWith(FFS_CONFIG.mcpAutoPrefix) ); if (mcpCondition) { const accounts = mcpCondition.argument ? mcpCondition.argument.split(',') : []; if (!accounts.includes(id)) { accounts.push(id); mcpCondition.argument = accounts.join(','); } mcpCondition.description = mcpConditionName; } else { mcpCondition = { description: mcpConditionName, priority: 1, dimension: 'AccountId', operator: 'IsOneOf', argumentDataType: 'ListString', argument: id, }; targetRule.conditions.push(mcpCondition); } // Step 6: Reassign priorities interface ConditionWithValueId { cond: { priority?: number; operator: string; description?: string }; valueId: string; } const allConditions: ConditionWithValueId[] = []; for (const rule of newFlag.rules) { for (const cond of rule.conditions) { if (cond.priority !== undefined && cond.operator !== 'DefaultValue') { allConditions.push({ cond, valueId: rule.value.id }); } } } const mcpConditions = allConditions.filter((c) => c.cond.description?.startsWith(FFS_CONFIG.mcpAutoPrefix) ); const otherConditions = allConditions.filter( (c) => !c.cond.description?.startsWith(FFS_CONFIG.mcpAutoPrefix) ); let priority = 1; for (const { cond, valueId } of mcpConditions) { cond.priority = priority++; cond.description = `${FFS_CONFIG.mcpAutoPrefix} [${valueId}]`; } for (const { cond } of otherConditions) { cond.priority = priority++; } // Step 7: Send PUT request const putRes = await httpRequest<FfsFlag>( `${FFS_CONFIG.baseUrl}${FFS_ENDPOINTS.flags}/${flagId}/`, { method: 'PUT', body: newFlag, } ); if (putRes.status !== 200) { throw new Error(`Failed to update flag: ${JSON.stringify(putRes.data)}`); } return { success: true, previousValue, currentValue: targetRule.value.value, }; } - src/index.ts:245-252 (registration)Tool registration using server.tool() with name 'ffs_update_account', description, and Zod schema defining flagId, id, and targetValueId as required string parameters.
server.tool( 'ffs_update_account', 'Update an AccountId or ExtensionId to use a specific Flag value. Uses MCP Auto Condition for management.', { flagId: z.string().describe('Complete FFS Flag ID'), id: z.string().describe('AccountId or ExtensionId to update'), targetValueId: z.string().describe('Target Value ID from ffs_get_flag_options'), }, - src/types.ts:23-31 (schema)FfsFlag interface definition that represents the flag structure manipulated by updateAccountValue, including id, rules with conditions, and other flag properties.
export interface FfsFlag { id: string; description?: string; dataType: string; status: string; defaultValue: string; rules: FfsRule[]; creationTime?: string; }