Connect Lucca to Claude: Access HR Records and Job Positions
Learn how to connect Lucca to Claude using a managed MCP server. This step-by-step guide covers handling Lucca's complex HR data models, rate limits, and tool calling.
If you need to give Claude read and write access to your Lucca HR suite, you need a Model Context Protocol (MCP) server. This server acts as the translation layer between Claude's tool calls and Lucca's underlying REST APIs. You can either build and maintain this infrastructure yourself, dealing with complex HR data models and strict rate limits, or use a managed integration platform like Truto to dynamically generate a secure, authenticated MCP server URL.
If your team uses ChatGPT, check out our guide on connecting Lucca to ChatGPT or explore our broader architectural overview on connecting Lucca to AI Agents.
Giving a Large Language Model (LLM) access to an HRIS like Lucca is a serious engineering challenge. You are not just exposing a flat database of users. You are exposing a highly normalized, multi-module system where an employee's identity, their employment contract, and their current job position are entirely separate resources. Every time the Lucca API updates an endpoint or changes a payload requirement, you have to update your server code, redeploy, and test the integration.
This guide breaks down exactly how to use Truto to generate a secure, managed MCP server for Lucca, connect it natively to Claude, and execute complex HR workflows using natural language.
The Engineering Reality of the Lucca API
A custom MCP server is a self-hosted integration layer. While the open MCP standard provides a predictable way for models to discover tools, the reality of implementing it against Lucca's APIs is painful.
If you decide to build a custom MCP server for Lucca, you own the entire API lifecycle. Here are the specific challenges you will face:
Highly Normalized HR Data Models
Unlike simpler SaaS directories where a "user" object contains everything from job title to department, Lucca's architecture is highly normalized. An employee record contains core identity data (name, email, birthdate). Their actual job is stored in a job-position record. Their legal contract is stored in an employment record. To answer a question like "Who are the senior engineers in the Paris office?", an AI agent must query employees, map them to job-positions, cross-reference departments, and filter by business-establishments. If you do not provide the LLM with explicit, separate tools for each of these resources, it will hallucinate the relationships. Truto exposes all of these as discrete, documented tools.
Complex Embedded Resource Expansion
To reduce API calls, Lucca allows for embedded resources in its responses, but this requires specific query formatting (often utilizing complex URL encoding or specific fields parameters). Building an MCP server that accurately instructs Claude on how to request and parse these embedded payloads requires massive, hand-maintained JSON schemas. Truto automatically generates these schemas from our live integration definitions, ensuring Claude always knows exactly what fields to expect.
Strict Rate Limits and IETF Compliance
Lucca enforces strict rate limits to protect its infrastructure. A common mistake engineers make is building custom MCP servers that attempt to silently absorb or retry these errors without informing the LLM. This causes Claude to hang or timeout. Truto takes a different approach: we do not retry, throttle, or apply backoff on rate limit errors. When Lucca returns an HTTP 429, Truto passes that error directly to the caller. We normalize the upstream rate limit info into standardized headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset) per the IETF spec. It is the responsibility of the caller (or the LLM orchestration layer) to read these headers and implement appropriate backoff logic.
How to Generate a Lucca MCP Server with Truto
Truto dynamically generates your MCP server from the Lucca integration's resource definitions. There is no code to write. You can generate the server via the Truto dashboard or programmatically via the API.
Method 1: Via the Truto UI
If you are setting this up for internal workflows, the dashboard is the fastest route:
- Navigate to the Integrated Accounts page in your Truto dashboard and select your connected Lucca account.
- Click the MCP Servers tab.
- Click Create MCP Server.
- Configure your server settings. You can name it, restrict it to specific HTTP methods (e.g., read-only), and set an optional expiration date.
- Click Create and copy the generated MCP server URL (e.g.,
https://api.truto.one/mcp/abc123def456).
Method 2: Via the Truto API
If you are deploying AI agents for your customers and need to spin up MCP servers programmatically, use the /mcp endpoint. The API generates a secure token, stores it, and returns a ready-to-use URL.
Endpoint: POST /integrated-account/:id/mcp
// Example: Generating a read-only Lucca MCP server via API
const response = await fetch('https://api.truto.one/integrated-account/YOUR_LUCCA_ACCOUNT_ID/mcp', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TRUTO_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: "Lucca HR Audit Server",
config: {
methods: ["read"], // Restricts the server to GET and LIST methods
tags: ["hr", "directory"]
},
expires_at: "2026-12-31T23:59:59Z"
})
});
const mcpServer = await response.json();
console.log(mcpServer.url);
// Output: https://api.truto.one/mcp/a1b2c3d4e5f6...Connecting the MCP Server to Claude
Once you have your Truto MCP URL, you can connect it to Claude. Because Truto handles the OAuth lifecycle and API translation remotely, you do not need to install local dependencies other than the standard remote transport layer.
Method A: Via the Claude Desktop UI
If you are using Claude Desktop (or the ChatGPT web UI, which follows a similar pattern):
- Open Claude Desktop and navigate to Settings -> Integrations.
- Click Add MCP Server (or Custom Connector).
- Paste the Truto MCP URL.
- Click Add. Claude will instantly handshake with Truto, pull the available Lucca tools, and make them available in your chat context.
Method B: Via Manual Config File
For custom AI agents, LangChain/LangGraph setups, or headless Claude Desktop deployments, you can add the server via your claude_desktop_config.json file.
We recommend using the official @modelcontextprotocol/server-sse package to handle the Server-Sent Events transport.
{
"mcpServers": {
"lucca-hris": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-sse",
"https://api.truto.one/mcp/YOUR_TRUTO_MCP_TOKEN"
]
}
}
}Restart Claude Desktop, and the model will have full access to the configured Lucca endpoints.
Security and Access Control
HR data is highly sensitive. Giving an LLM raw access to an HRIS requires strict governance. Truto MCP servers include built-in security primitives to restrict what the model can see and do.
- Method Filtering (
config.methods): Restrict the server to safe operations. Setting this to["read"]ensures the LLM can only executegetandlistoperations, preventing it from accidentally deleting an employee or updating a contract. - Tag Filtering (
config.tags): Group tools by function. You can restrict the MCP server to only expose tools tagged withdirectory, ensuring the LLM cannot access payroll or webhook endpoints. - Secondary Authentication (
require_api_token_auth): By default, the MCP token in the URL acts as the authentication layer. For higher security, setting this flag totruerequires the connecting client to also pass a valid Truto API token in theAuthorizationheader. - Automatic Expiration (
expires_at): Generate short-lived access. Setting an ISO datetime schedules a durable cleanup alarm that completely destroys the MCP server and its KV records at the specified time, perfect for temporary contractor audits.
Core Lucca MCP Tools
Truto exposes the entirety of the Lucca API as discrete tools. Here are the core tools your AI agent will use most frequently when interacting with Lucca.
List All Employees
list_all_lucca_employees
This is the foundational tool for reading the employee directory. It returns core fields like id, givenName, familyName, employeeNumber, status, and email. It also returns pointers to the applicableEmployment and applicableJobPosition resources.
Contextual note: Because Lucca paginates data, Claude will use this tool to sweep the directory. If the response contains a next_cursor, Claude will pass it back in subsequent calls.
"I need a list of all active employees in our Lucca directory. Please extract their names, email addresses, and employee numbers into a markdown table."
Get Single Employee By ID
get_single_lucca_employee_by_id
Retrieves the complete profile of a specific employee using their unique id. This tool frequently returns embedded objects, allowing the model to see the connected employment and job-position data without making secondary calls.
Contextual note: Use this when you have an identifier from a previous list operation or a webhook payload and need deep context on a single individual.
"Look up the employee profile for ID 482. Summarize their current status, birthdate, and the department ID they belong to based on the embedded job position data."
List All Job Positions
list_all_lucca_job_positions
Job positions in Lucca define a role at a specific time. This tool lists records containing jobTitle, department, businessEstablishment, manager, and the startsOn and endsOn dates.
Contextual note: This is critical for understanding the org chart. An employee might exist, but their job-position dictates who their manager is and what department they sit in.
"List all the job positions currently active in Lucca. Filter through the results to find any positions where the jobTitle includes 'Engineer' and tell me who their managers are."
Get Single Department By ID
get_single_lucca_department_by_id
Retrieves the details of a specific department, including its name, description, parent department, level (depth in the org hierarchy), and the department manager.
Contextual note: Lucca uses nested hierarchies for departments. Claude can use this tool iteratively to walk up or down the org chart by following the parent IDs.
"Get the details for department ID 12. Tell me the name of the department, who the manager is, and the ID of its parent department."
List All Probationary Periods
list_all_lucca_probationary_periods
Retrieves all probationary periods, returning the startsOn, endsOn, and extendedEndsOn dates, alongside a reference to the specific employment record it applies to.
Contextual note: This is incredibly useful for automated HR alerts. AI agents can check this endpoint to identify which employees are approaching the end of their probation and draft review reminders for their managers.
"Fetch all probationary periods in Lucca. Identify any periods where the 'endsOn' date is within the next 30 days, and list the employment references for those records."
List All Webhook Deliveries
list_all_lucca_webhook_deliveries
Retrieves the logs of outbound webhook events sent by Lucca. It returns the delivery status, attemptsCount, nextAttemptAt, and a reference to the webhookEndpoint.
Contextual note: IT administrators can use Claude to audit integration health. If syncs are failing between Lucca and an external system, Claude can inspect the webhook deliveries to identify failing endpoints.
"Check the recent webhook deliveries in Lucca. Find any deliveries that have a status of 'failed' or 'undelivered' and summarize the endpoints that are experiencing issues."
Workflows in Action
With the MCP server connected, Claude can orchestrate complex, multi-step HR workflows by combining tools dynamically.
Scenario 1: Auditing Employee Org Structure
When a new IT administrator needs to map out a specific team, they can ask Claude to traverse the highly normalized Lucca data model to build a cohesive report.
"Find the employee named 'Sarah Jenkins'. Figure out what her current job title is, who her manager is, and what department she works in. Provide a summary of her place in the org chart."
Execution Flow:
- Claude calls
list_all_lucca_employeeswith query parameters to search for "Sarah Jenkins". - The server returns her core employee record, which includes her
idand a pointer to herapplicableJobPosition. - Claude calls
get_single_lucca_job_position_by_idusing the ID found in step 2. - The server returns the job position, revealing her
jobTitle("Senior Product Designer"), hermanager's ID, and herdepartmentID. - Claude calls
get_single_lucca_department_by_idto resolve the department name. - Claude processes all the JSON responses and outputs a clean, human-readable summary of her role and reporting structure.
Scenario 2: Probationary Period Review Audit
HR teams spend hours tracking compliance dates. You can instruct Claude to automate this audit process.
"Review the probationary periods in Lucca. Find any that are ending in the current month. For each one, get the employee's name and their manager's ID so I know who needs to submit a review."
Execution Flow:
- Claude calls
list_all_lucca_probationary_periods. - Claude filters the returned arrays for objects where
endsOnorextendedEndsOnfalls within the current month. - For each matching record, Claude extracts the
employmentreference ID. - Claude calls
get_single_lucca_employment_by_idto find the associatedemployeeID. - Claude calls
get_single_lucca_employee_by_idto get the employee's name and theirapplicableJobPosition. - Finally, Claude calls
get_single_lucca_job_position_by_idto find themanagerassigned to that role, compiling the final alert list for HR.
Handling Rate Limits in Production
If you ask Claude to summarize 500 employees, the model will iterate through the list using pagination cursors. Eventually, the Lucca API will hit its rate limit and return an HTTP 429 error.
Truto does not hide this from your agent. Attempting to silently buffer or queue requests at the proxy layer often leads to connection timeouts and hallucinated states in the LLM.
Instead, Truto passes the 429 error directly back through the MCP protocol, alongside normalized rate limit headers:
ratelimit-limit: The maximum number of requests allowed in the current window.ratelimit-remaining: How many requests you have left.ratelimit-reset: The exact Unix timestamp when the limit resets.
When Claude encounters an isError: true response containing these headers, you can instruct it in your system prompt to pause execution, wait until the ratelimit-reset timestamp has passed, and then automatically retry the tool call.
Summary
Connecting Claude to Lucca transforms a static HR system into an interactive, agentic platform. Instead of forcing HR teams to navigate complex UIs to cross-reference employment contracts with job positions, AI agents can query the data structure directly, resolving embedded resources and mapping org charts in seconds.
By leveraging Truto's dynamic MCP server generation, you bypass the massive engineering overhead of maintaining OAuth lifecycles, writing JSON schemas, and normalizing pagination. You get a secure, documented, and fully managed integration layer that keeps your LLMs grounded in actual SaaS data.
FAQ
- How do I restrict Claude from modifying HR data in Lucca?
- When generating the Truto MCP server, you can apply method filtering by setting the configuration to `methods: ["read"]`. This ensures the MCP server only exposes GET and LIST endpoints, physically preventing the LLM from making write or delete requests.
- Does Truto handle Lucca API rate limits?
- Truto normalizes Lucca's rate limit headers into standard IETF formats (ratelimit-limit, ratelimit-remaining, ratelimit-reset) but passes HTTP 429 errors directly to the caller. The LLM or your orchestration framework must handle the retry and backoff logic.
- How does Claude handle Lucca's separate employee and job position data?
- Lucca uses a highly normalized data model. Truto exposes distinct tools for employees, employments, and job positions. Claude can iteratively call these tools—for example, getting an employee's ID and then querying the job position endpoint to find their manager or department.