Skip to main content
Glama
Lucid-Drone-Technologies

Paylocity MCP Server

add_employee

Onboard new employees by creating records with personal information, job details, and compensation data in the Paylocity system. Securely handles required SSN encryption and returns the new employee ID.

Instructions

Add a new employee to the system (onboarding). Creates the employee record with personal info, job details, and compensation. SSN is required by Paylocity but will not be stored in conversation — pass it directly and it will be sent encrypted. Returns the new employee ID.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
companyIdNoPaylocity company ID (defaults to PAYLOCITY_COMPANY_ID env var)
firstNameYes
lastNameYes
ssnYesSocial Security Number (XXX-XX-XXXX)
birthDateYesYYYY-MM-DD
genderNo
hireDateYesYYYY-MM-DD
address1Yes
cityYes
stateYes2-letter state code
zipYes
personalEmailAddressNo
personalMobilePhoneNo
workEmailAddressNo
jobTitleNo
costCenter1NoDepartment/cost center code
employeeTypeNoRFT=Regular Full-Time, RPT=Regular Part-Time, TFT=Temp Full-Time, TPT=Temp Part-Time
supervisorEmployeeIdNo
payTypeNoSalary or Hourly
annualSalaryNo
baseRateNoHourly rate
payFrequencyNoS=Semi-monthly, B=Biweekly, W=Weekly, M=Monthly
defaultHoursNo

Implementation Reference

  • Registration and implementation of the 'add_employee' tool, which handles onboarding by creating a new employee record via the Paylocity API.
    server.tool(
      "add_employee",
      `Add a new employee to the system (onboarding). Creates the employee record with
    personal info, job details, and compensation. SSN is required by Paylocity but will
    not be stored in conversation — pass it directly and it will be sent encrypted.
    Returns the new employee ID.`,
      {
        companyId: companyIdParam,
        firstName: z.string(),
        lastName: z.string(),
        ssn: z.string().describe("Social Security Number (XXX-XX-XXXX)"),
        birthDate: z.string().describe("YYYY-MM-DD"),
        gender: z.enum(["M", "F"]).optional(),
        hireDate: z.string().describe("YYYY-MM-DD"),
        // Address
        address1: z.string(),
        city: z.string(),
        state: z.string().describe("2-letter state code"),
        zip: z.string(),
        // Contact
        personalEmailAddress: z.string().optional(),
        personalMobilePhone: z.string().optional(),
        workEmailAddress: z.string().optional(),
        // Job
        jobTitle: z.string().optional(),
        costCenter1: z.string().optional().describe("Department/cost center code"),
        employeeType: z
          .string()
          .optional()
          .describe("RFT=Regular Full-Time, RPT=Regular Part-Time, TFT=Temp Full-Time, TPT=Temp Part-Time"),
        supervisorEmployeeId: z.string().optional(),
        // Pay
        payType: z
          .enum(["Salary", "Hourly"])
          .optional()
          .describe("Salary or Hourly"),
        annualSalary: z.number().optional(),
        baseRate: z.number().optional().describe("Hourly rate"),
        payFrequency: z
          .string()
          .optional()
          .describe("S=Semi-monthly, B=Biweekly, W=Weekly, M=Monthly"),
        defaultHours: z.number().optional(),
      },
      async ({
        companyId,
        firstName,
        lastName,
        ssn,
        birthDate,
        gender,
        hireDate,
        address1,
        city,
        state,
        zip,
        personalEmailAddress,
        personalMobilePhone,
        workEmailAddress,
        jobTitle,
        costCenter1,
        employeeType,
        supervisorEmployeeId,
        payType,
        annualSalary,
        baseRate,
        payFrequency,
        defaultHours,
      }) => {
        try {
          const cid = resolveCompanyId(companyId);
    
          const newEmployee: Record<string, any> = {
            companyNumber: cid,
            autoGenerateEmployeeId: true,
            firstName,
            lastName,
            ssn,
            birthDate,
            hireDate,
            employeeStatus: "A",
            address1,
            city,
            state,
            zip,
            country: "USA",
          };
    
          if (gender) newEmployee.sex = gender;
          if (personalEmailAddress)
            newEmployee.personalEmailAddress = personalEmailAddress;
          if (personalMobilePhone)
            newEmployee.personalMobilePhone = personalMobilePhone;
          if (workEmailAddress) newEmployee.workEmailAddress = workEmailAddress;
          if (jobTitle) newEmployee.title = jobTitle;
          if (costCenter1) newEmployee.costCenter1 = costCenter1;
          if (employeeType) newEmployee.employmentType = employeeType;
          if (supervisorEmployeeId)
            newEmployee.supervisorID = supervisorEmployeeId;
          if (payType) {
            newEmployee.rateCode = payType;
            newEmployee.ratePer = payType === "Hourly" ? "Hour" : "Year";
          }
          if (annualSalary) newEmployee.annualSalary = annualSalary;
          if (baseRate) newEmployee.baseRate = baseRate;
          if (payFrequency) newEmployee.payFrequency = payFrequency;
          if (defaultHours) newEmployee.defaultHours = defaultHours;
    
          const result = await client.post(
            `/v2/companies/${cid}/employees`,
            { newEmployee }
          );
    
          // Invalidate directory cache
          directoryCacheTime = 0;
    
          return ok({ success: true, result: redact(result) });
        } catch (e) {
          return err(e);
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description carries full burden. Discloses important security behavior (SSN encrypted, not stored in conversation) and return value ('Returns the new employee ID'). Does not mention error scenarios or reversibility.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences with zero waste. Front-loaded with purpose ('Add a new employee'), followed by scope, security-critical SSN handling, and return value. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 23 parameters and mutation nature, description adequately covers essential security context (SSN encryption) and output (employee ID). Missing explicit required vs optional guidance and error handling, but sufficient for correct invocation given schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is low (43%), so description must compensate. Provides high-level categories ('personal info, job details, and compensation') mapping to parameter groups and highlights SSN specifically. However, does not detail the majority of undocumented parameters (firstName, lastName, address1, etc.).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description uses specific verbs ('Add', 'Creates') with clear resource ('employee'). Explicitly mentions 'onboarding' and 'new' to distinguish from sibling update_employee, and 'Creates' distinguishes from get/search siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear context ('onboarding') indicating when to use for new hires. Includes critical usage instruction about SSN handling ('pass it directly'). Could improve by explicitly contrasting with update_employee for existing records.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/Lucid-Drone-Technologies/paylocity-mcp'

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