UNPKG

@toriihq/torii-mcp

Version:

Model Context Protocol server for Torii API

99 lines (97 loc) 5.37 kB
import { z } from 'zod'; import { makeApiRequest } from './api.js'; import { FUNCTION_NAME_TO_API_PARAMS } from '../api/filters.js'; import { convertArgsToParameters } from './shared.types.js'; // API Functions for Users export async function getUsers(params) { const apiRequest = FUNCTION_NAME_TO_API_PARAMS.list_users(params ? convertArgsToParameters(params) : []); return makeApiRequest(apiRequest.path, apiRequest.method, undefined, apiRequest.headers); } export async function getUserById(idUser, params) { const queryParams = params ? `?${new URLSearchParams(params).toString()}` : ''; return makeApiRequest(`/users/${idUser}${queryParams}`); } // Register Users tools with the MCP server export function registerUsersTools(server) { // List Users Tool server.tool('list_users', ` <use_case> Use this tool to list all users in the organization </use_case> <important_notes> - ALWAYS use AT LEAST one of: aggs, baseFilters and filters (see filters_schema below) for better results. - ALWAYS user the "view" filter to filter out irrelevant data. If not specified, use the "currentEmployees" view. - Use the aggs property to perform aggregations over the data, such as grouping, calculations: sum, average, minimum, maximum, etc, date range and more. Follow the aggregations_schema below. Aggregated data is returned under the "aggregations" property. - ALWAYS use the fields property and ask only for the fields you need. - Use the get_user_fields tool to list the fields to pass in the "fields" parameter. </important_notes> <filters_schema> Array of { key: string op: equals|notEquals|contains|notContains|anyOf|noneOf|allOf|isExactly|isSet|isNotSet|gt|gte|lt|lte|dayAfter|dayOnOrAfter|dayBefore|dayOnOrBefore|nested|relativeDateToday|relativeDateOn|relativeDateLess|relativeDateMore|exists|notExists|or|and value: changes based on the type of field used as key } </filters_schema> <aggregations_schema> AGGREGATION_TYPES = metric | groupBy | date_range | date_histogram METRIC_FUNCTIONS = sum | avg | max | min (and "total" if aggregationType = groupBy) AGGREGATION_SORT_ORDERS = min | max <schema> { field: string, aggregationType: AGGREGATION_TYPES, options: { metricFunction: METRIC_FUNCTIONS, size: number (max: 100), sort: { field: string, aggFunc: METRIC_FUNCTIONS, order: AGGREGATION_SORT_ORDERS }, aggs: Nested aggregation with the same structure as the parent } </schema> </aggregations_schema> `, { cursor: z .string() .optional() .describe("Pagination cursor taken from the previous response's nextCursor property"), baseFilters: z .string() .optional() .describe('JSON string representing filters schema. Structure: "{\"email\":string,\"lifecycleStatus\":string,\"isDeletedInIdentitySources\":true if the user has left the organization, false otherwise,\"firstName\":string,\"lastName\":string,\"view\":currentEmployees|pastEmployees|allEmployees|currentUsers|pastUsers|allUsers|externalUsers, \"idUsers\":comma separated list of idUser with a maximum of 50 IDs}"'), filters: z .string() .optional() .describe('JSON string representing filters schema: "[{\"key\":[field_name],\"op\":operation,\"value\":[field_value}]"; the list can contain multiple filters combined in an "AND" relation'), fields: z .string() .optional() .describe('Comma-separated list of fields to return for each application; Allowed fields: idOrg, firstName, lastName, email, creationTime, idRole, lifecycleStatus, isDeletedInIdentitySources, isExternal, activeAppsCount, role, additionalEmails and all fields from the get_user_fields tool'), aggs: z .string() .optional() .describe('JSON string representing aggregation schema. Structure: "{\"field\":\"string\", \"aggregationType\":\"metric|groupBy|date_range|date_histogram\", \"options\":{\"size\":integer, \"sort\":{\"field\":\"string\",\"order\":\"desc|asc\",\"aggFunc\":\"sum|avg|max|min\"}, \"metricFunction\":\"total|sum|avg|max|min\", \"hardBounds\":{\"min\":\"string\",\"max\":\"string\"}, \"extendedBounds\":{\"min\":\"string\",\"max\":\"string\"}, \"datePeriod\":\"weekly|monthly|quarterly|yearly\"}, \"aggs\":Nested aggregation with the same structure as the parent}"') }, async (params) => { const users = await getUsers(params); return { content: [{ type: 'text', text: JSON.stringify(users, null, 2) }] }; }); // Get User Tool server.tool('get_user', 'Get details of a specific user by ID', { id: z.string().describe('Unique user identifier'), fields: z.string().optional().describe('Comma-separated list of fields to return') }, async ({ id, fields }) => { const params = {}; if (fields) params.fields = fields; const user = await getUserById(id, params); return { content: [{ type: 'text', text: JSON.stringify(user, null, 2) }] }; }); } //# sourceMappingURL=users.js.map