The getStaff tool retrieves staff member records from the Firebase/Firestore database with support for pagination and sorting.
tools/getStaff.js
Retrieves staff members for the authenticated account with cursor-based pagination support. Staff members are employees who can be assigned to orders as technicians or responsible parties. Staff are retrieved from the Firestore path: /Accounts/{accountId}/Staff.
{
limit?: number; // Number of records to retrieve (1-100, default: 50)
cursor?: string; // Document ID for cursor-based pagination
orderBy?: string; // Field to order by (default: "name")
orderDirection?: "asc" | "desc"; // Sort direction (default: "asc")
cursorDirection?: "next" | "previous"; // Direction for pagination (default: "next")
includeTotal?: boolean; // Include total count of all staff (default: false)
}
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
limit |
number | No | 50 | Maximum number of staff to return (1-100) |
cursor |
string | No | - | Document ID to start pagination from |
orderBy |
string | No | “name” | Field name to sort by |
orderDirection |
enum | No | “asc” | Sort direction: “asc” or “desc” |
cursorDirection |
enum | No | “next” | Pagination direction: “next” or “previous” |
includeTotal |
boolean | No | false | Whether to include total count (expensive) |
{
staff: Staff[];
pagination: PaginationMetadata;
}
{
id: string; // Firestore document ID
path: string; // Full Firestore path
active?: boolean; // Whether the staff member is active
createdAt?: string | null; // Creation timestamp (locale string)
createdBy?: string; // ID of the user who created this record
email?: string; // Staff member email (optional)
mobilePhone?: string; // Mobile phone number
name?: string; // Staff member name (optional)
ownedBy?: string; // Owner ID
phone?: string; // Landline phone number
}
Note: Both name and email are optional fields. Some staff records may have only name, only email, or both.
{
limit: number; // Applied limit
hasMore: boolean; // Whether more results exist
nextCursor: string | null; // Cursor for next page
previousCursor: string | null; // Cursor for previous page
total?: number | null; // Total count (if includeTotal was true)
}
// Get first 10 staff members
const result = await getStaff(context, {
limit: 10
});
console.log(result.staff); // Array of 10 staff members
console.log(result.pagination); // Pagination metadata
// First page
const page1 = await getStaff(context, {
limit: 20,
orderBy: "name",
orderDirection: "asc"
});
// Next page
const page2 = await getStaff(context, {
limit: 20,
cursor: page1.pagination.nextCursor,
cursorDirection: "next"
});
// Get staff sorted by email
const result = await getStaff(context, {
limit: 10,
orderBy: "email",
orderDirection: "asc"
});
// Get all staff members for dropdown/selection
const result = await getStaff(context, {
limit: 100
});
console.log(`Found ${result.staff.length} staff members`);
const result = await getStaff(context, {
limit: 10,
includeTotal: true
});
console.log(`Account has ${result.pagination.total} total staff members`);
// Get staff member by document ID
const allStaff = await getStaff(context, { limit: 100 });
const staffMember = allStaff.staff.find(s => s.id === "staff123");
console.log(staffMember.name, staffMember.email);
The tool transforms Firestore documents by:
id and full pathconst transformStaff = (doc) => ({
id: doc.id,
path: doc.ref.path,
...doc.data(),
});
By default, staff are ordered by name in ascending order for alphabetical listing.
Staff records may have minimal data:
| Error | Cause | Solution |
|---|---|---|
| “Error fetching staff: [message]” | Firestore query failed | Check Firebase connection and permissions |
| “Failed to fetch staff.” | Query error | Verify authentication and account access |
| Validation error | Invalid input parameters | Ensure parameters match the input schema |
Errors are logged and a generic error message is thrown:
catch (error) {
console.error("Error fetching staff:", error);
throw new Error("Failed to fetch staff.");
}
/Accounts/{accountId}/Staff/{staffId}
- name: string (optional)
- email: string (optional)
Note: The schema is intentionally minimal. Additional fields may exist in the database but are not enforced by the Zod schema.
Staff members are referenced in orders via the technician_staff and responsible_staff fields:
// Get orders with staff information
const orders = await getOrders(context, { limit: 10 });
// Staff data is automatically embedded
orders.orders.forEach(order => {
if (order.technician_staff) {
console.log(`Technician: ${order.technician_staff.name}`);
}
if (order.responsible_staff) {
console.log(`Responsible: ${order.responsible_staff.name}`);
}
});
// Fetch all staff for a selection UI
const result = await getStaff(context, {
limit: 100,
orderBy: "name",
orderDirection: "asc"
});
// Format for dropdown
const staffOptions = result.staff.map(s => ({
value: s.id,
label: s.name || s.email || s.id,
email: s.email
}));
console.log(staffOptions);
// [
// { value: "staff1", label: "John Doe", email: "john@example.com" },
// { value: "staff2", label: "Jane Smith", email: "jane@example.com" },
// ...
// ]