Skip to main content
Glama
roles.ts8.18 kB
import { z } from 'zod'; import { createTool } from '../base.js'; import { floatApi } from '../../services/float-api.js'; import { roleSchema, rolesResponseSchema, Role } from '../../types/float.js'; // List roles with optional filtering export const listRoles = createTool( 'list-roles', 'List all roles with optional filtering by status, department, or active status', z.object({ active: z.number().optional().describe('Filter by active status (0=archived, 1=active)'), department_id: z.number().optional().describe('Filter by department ID'), level: z.number().optional().describe('Filter by role level/hierarchy'), page: z.number().optional().describe('Page number for pagination'), 'per-page': z.number().optional().describe('Number of items per page (max 200)'), }), async (params) => { const response = await floatApi.getPaginated('/roles', params, rolesResponseSchema); return response; } ); // Get role details export const getRole = createTool( 'get-role', 'Get detailed information about a specific role', z.object({ role_id: z.union([z.string(), z.number()]).describe('The role ID (role_id)'), }), async (params) => { const role = await floatApi.get(`/roles/${params.role_id}`, roleSchema); return role; } ); // Create role export const createRole = createTool( 'create-role', 'Create a new role with permissions and settings', z.object({ name: z.string().describe('Role name (required)'), description: z.string().optional().describe('Role description'), default_hourly_rate: z.string().optional().describe('Default hourly rate for this role'), permissions: z.array(z.string()).optional().describe('List of permissions for this role'), active: z.number().optional().describe('Active status (1=active, 0=archived)'), department_id: z.number().optional().describe('Department ID if role is department-specific'), level: z.number().optional().describe('Role level/hierarchy'), is_system_role: z .number() .optional() .describe('Whether this is a system role (1=system, 0=custom)'), }), async (params) => { const role = await floatApi.post('/roles', params, roleSchema); return role; } ); // Update role export const updateRole = createTool( 'update-role', 'Update an existing role with new information or permissions', z.object({ role_id: z.union([z.string(), z.number()]).describe('The role ID (role_id)'), name: z.string().optional().describe('Role name'), description: z.string().optional().describe('Role description'), default_hourly_rate: z.string().optional().describe('Default hourly rate for this role'), permissions: z.array(z.string()).optional().describe('List of permissions for this role'), active: z.number().optional().describe('Active status (1=active, 0=archived)'), department_id: z.number().optional().describe('Department ID if role is department-specific'), level: z.number().optional().describe('Role level/hierarchy'), is_system_role: z .number() .optional() .describe('Whether this is a system role (1=system, 0=custom)'), }), async (params) => { const { role_id, ...updateData } = params; const role = await floatApi.patch(`/roles/${role_id}`, updateData, roleSchema); return role; } ); // Delete role export const deleteRole = createTool( 'delete-role', 'Delete a role (archives it in Float). Note: Roles assigned to users should be reassigned first.', z.object({ role_id: z.union([z.string(), z.number()]).describe('The role ID (role_id)'), }), async (params) => { await floatApi.delete(`/roles/${params.role_id}`); return { success: true, message: 'Role deleted successfully' }; } ); // Role-based access control helper tools // Get roles by permission export const getRolesByPermission = createTool( 'get-roles-by-permission', 'Get all roles that have a specific permission', z.object({ permission: z.string().describe('The permission to search for'), active: z.number().optional().describe('Filter by active status (0=archived, 1=active)'), }), async (params) => { // First get all roles const roles = await floatApi.getPaginated( '/roles', { active: params.active }, rolesResponseSchema ); // Filter roles that have the specified permission const filteredRoles = roles.filter( (role) => role.permissions && role.permissions.includes(params.permission) ); return filteredRoles; } ); // Get role permissions export const getRolePermissions = createTool( 'get-role-permissions', 'Get all permissions for a specific role', z.object({ role_id: z.union([z.string(), z.number()]).describe('The role ID (role_id)'), }), async (params) => { const role = await floatApi.get(`/roles/${params.role_id}`, roleSchema); return { role_id: role.role_id, role_name: role.name, permissions: role.permissions || [], active: role.active, }; } ); // Update role permissions export const updateRolePermissions = createTool( 'update-role-permissions', 'Update permissions for a specific role', z.object({ role_id: z.union([z.string(), z.number()]).describe('The role ID (role_id)'), permissions: z.array(z.string()).describe('New list of permissions for this role'), replace: z .boolean() .optional() .describe('Whether to replace all permissions (true) or merge with existing (false)'), }), async (params) => { const { role_id, permissions, replace = true } = params; let finalPermissions = permissions; if (!replace) { // Get current permissions and merge const currentRole = await floatApi.get(`/roles/${role_id}`, roleSchema); const currentPermissions = currentRole.permissions || []; // Remove duplicates and merge const permissionSet = new Set([...currentPermissions, ...permissions]); finalPermissions = Array.from(permissionSet); } const role = await floatApi.patch( `/roles/${role_id}`, { permissions: finalPermissions }, roleSchema ); return role; } ); // Get role hierarchy export const getRoleHierarchy = createTool( 'get-role-hierarchy', 'Get roles organized by hierarchy levels', z.object({ department_id: z.number().optional().describe('Filter by department ID'), active: z.number().optional().describe('Filter by active status (0=archived, 1=active)'), }), async (params) => { const roles = await floatApi.getPaginated('/roles', params, rolesResponseSchema); // Group roles by level const hierarchy = roles.reduce( (acc, role) => { const level = role.level || 0; if (!acc[level]) { acc[level] = []; } acc[level].push(role); return acc; }, {} as Record<number, Role[]> ); return hierarchy; } ); // Check role access export const checkRoleAccess = createTool( 'check-role-access', 'Check if a role has specific permissions (useful for RBAC implementation)', z.object({ role_id: z.union([z.string(), z.number()]).describe('The role ID (role_id)'), required_permissions: z.array(z.string()).describe('List of permissions to check for'), require_all: z .boolean() .optional() .describe('Whether all permissions are required (true) or just one (false)'), }), async (params) => { const { role_id, required_permissions, require_all = true } = params; const role = await floatApi.get(`/roles/${role_id}`, roleSchema); const rolePermissions = role.permissions || []; let hasAccess: boolean; if (require_all) { hasAccess = required_permissions.every((perm) => rolePermissions.includes(perm)); } else { hasAccess = required_permissions.some((perm) => rolePermissions.includes(perm)); } return { role_id: role.role_id, role_name: role.name, has_access: hasAccess, role_permissions: rolePermissions, required_permissions, missing_permissions: required_permissions.filter((perm) => !rolePermissions.includes(perm)), }; } );

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/asachs01/float-mcp'

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