Breathe HR MCP server for AI agents

Live

API KEY

HR OPERATIONS

Productivity

Breathe HR gives your agent HR operations for your Breathe account: read employee records and job history, approve or reject leave requests, record sickness and training, manage expenses and claims, and review salaries, bonuses, and benefits.

  • Per-user credentials: each call uses the actual user's API key, never a shared bot.
  • Encrypted per-tenant vault: AES-256, resolved at request time, never in LLM context.
  • Scoped before every call: pre-call scope check, 90-day SIEM-exportable audit chain.
Breathe HR
agent · Acme Q3
Run
Which leave requests are waiting for approval?
S
breathehr_leave_requests_list
112ms
HR agent
3 leave requests are pending. Tom Hughes asked for 5 days from 14 April, the longest of the three.
Sources: 3 leave requests
breathehr
3 requests
18:29
Message Claude...

Tools your HR agent reaches for on Breathe HR, scoped per user.

CALL ANY TOOL
61 tools for HR operations in Breathe HR: read employees and departments, approve leave, record sickness and training, manage expenses and claims, and review pay records.
breathehr_absence_cancel
Cancel absence
Cancel an absence by ID, optionally recording a reason. Returns the cancellation as a leave request record with id, dates, action and status. Use breathehr_absence_cancel to withdraw booked time off. Use breathehr_leave_request_reject to turn down a pending request.
Parameters
Name
Type
Required
Description
absence_id
integer
Required
ID of the absence to cancel, from breathehr_absences_list. Example: 5678.
reason
string
Optional
Reason for cancelling the absence. Example: Trip postponed.
breathehr_absences_list
List absences
breathehr_account_get
Get account
breathehr_bonuses_list
List bonuses
breathehr_company_documents_list
List company documents
breathehr_company_training_types_list
List company training types
breathehr_department_benefits_list
List department benefits
breathehr_department_leave_requests_list
List department leave requests
breathehr_departments_list
List departments
breathehr_employee_absences_list
List employee absences
breathehr_employee_bonuses_list
List employee bonuses
breathehr_employee_change_request_approve
Approve employee change request
breathehr_employee_change_request_create
Create employee change request
breathehr_employee_get
Get employee
breathehr_employee_holiday_years_list
List employee holiday years
breathehr_employee_leave_request_create
Create employee leave request
breathehr_employee_leave_requests_list
List employee leave requests
breathehr_employee_sicknesses_list
List employee sicknesses
breathehr_expense_claim_create
Create expense claim
breathehr_expense_claim_delete
Delete expense claim
breathehr_expense_claims_list
List expense claims
breathehr_expense_get
Get expense
breathehr_expense_update
Update expense
breathehr_holiday_allowances_list
List holiday allowances
breathehr_leave_request_approve
Approve leave request
breathehr_locations_list
List locations
breathehr_salaries_list
List salaries
breathehr_sickness_delete
Delete sickness
breathehr_sickness_update
Update sickness
breathehr_statutory_holiday_countries_list
List statutory holiday countries

For more tools, view docs.

Build your Agent
Same auth pattern across LangChain, OpenAI, Anthropic, and Google ADK.
Python · LlamaIndex
import { ScalekitClient } from "@scalekit-sdk/node";
import { createReactAgent } from "@langchain/langgraph/prebuilt";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);

// Breathe HR tools scoped to this user
const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["breathehr"], toolNames: [
    "breathehr_leave_requests_list",
    "breathehr_leave_request_approve",
    "breathehr_absences_list"] },
  pageSize: 100,
});

const agent = createReactAgent({ llm, tools });
await agent.invoke({ messages: [{ role: "user", content: "List pending leave requests and approve Tom Hughes's holiday request" }] });
import OpenAI from "openai";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);
const openai = new OpenAI();

const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["breathehr"] }, pageSize: 100,
});

const res = await openai.chat.completions.create({
  model: "gpt-5",
  messages: [{ role: "user", content: "List pending leave requests and approve Tom Hughes's holiday request" }],
  tools,
});

// Execute the tool call with the user's vaulted Breathe HR API key
await sk.tools.executeTool(res.choices[0].message.tool_calls[0], "user_123");
import Anthropic from "@anthropic-ai/sdk";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);
const anthropic = new Anthropic();

const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["breathehr"] }, pageSize: 100,
});

const msg = await anthropic.messages.create({
  model: "claude-sonnet-5",
  max_tokens: 1024,
  messages: [{ role: "user", content: "List pending leave requests and approve Tom Hughes's holiday request" }],
  tools,
});

// Tool call runs with the user's vaulted Breathe HR API key
await sk.tools.executeTool(msg.content, "user_123");
import { Agent } from "@google/adk/agents";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);

const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["breathehr"] }, pageSize: 100,
});

const agent = new Agent({
  name: "hr_agent",
  model: "gemini-2.5-pro",
  instruction: "Breathe HR tools scoped to this user",
  tools,
});

await agent.run("List pending leave requests and approve Tom Hughes's holiday request");
Try these prompts
Copy any prompt into your agent. Each maps directly to a Breathe HR tool. Click to copy, paste into your agent, done.
People
Copy the prompt
Copied
Show Tom Hughes's job history.
Copy the prompt
Copied
Create an employee record for Priya Shah starting 3 June.
Copy the prompt
Copied
Approve the pending address change request for Tom Hughes.
Leave and sickness
Copy the prompt
Copied
Which leave requests are pending?
Copy the prompt
Copied
Approve Tom Hughes's holiday request from 14 April.
Copy the prompt
Copied
Record a 2-day sickness absence for Priya Shah starting today.
Expenses and pay
Copy the prompt
Copied
List expense claims submitted this month.
Copy the prompt
Copied
Approve Priya Shah's travel expense claim.
Copy the prompt
Copied
Show salary records for the Engineering department.
SEE HOW AUTH WORKS
Each user connects their own Breathe HR API key once, and Scalekit sends it with every call. Keys stay vaulted, every call is scope checked, and every action is logged.
1
Authorize
Your user connects
Breathe HR
once. We tie it to their identity and the meetings they approved — no shared bot account, no org-wide access
Who:
user ‘A’
when:
Once per user
access:
Limited to user
2
Store
Their
Breathe HR
token lives in a vault scoped to them. User A's meetings are never reachable by an agent acting for user B, even on the same connection
vault:
encrypted
scope:
per-user
tokens:
auto-refreshed
3
Resolve
When your agent calls a
Breathe HR
tool, we fetch the right token server-side. It never touches your agent, never appears in the LLM context, never shows up in your logs
speed:
~40ms
check:
before every call
seen by:
nobody
4
Audit
Every
Breathe HR
tool call is logged — who triggered it, which meeting was fetched, what came back. 90 days of history, tied to the user who authorized it
history:
90 days
export:
SIEM-ready
logged:
every call
Test other agents
See the same per-user auth pattern across other HR and productivity connectors.
People Ops and HR teams
Performance review collector
Collects review feedback from Airtable and Google Forms scoped to each manager's direct reports, writes per-employee summaries to Notion, and DMs the manager a Slack digest.
People Ops and HR teams
Offer letter routing agent
Drafts the offer in PandaDoc, blocks on the hiring manager's approval in Slack, then emails the candidate their e-signature link. Every call runs as the recruiter who triggered it, never a shared HR bot.
Test other agents
See the same per-user auth pattern across other HR and productivity connectors.
PEOPLE OPS
Performance review collector agent
Collect review feedback from Airtable and Google Forms per manager, summarise each report in Notion, and DM the digest in Slack.
PEOPLE OPS
Offer letter routing agent
Draft the offer in PandaDoc, gate it on hiring manager approval in Slack, then email the candidate their signature link.
Why Scalekit
Secure your agent's access. Connectors ship in minutes
01.
Shared tokens break per-user analytics
A shared Breathe HR API key looks fine in a demo. In production every leave approval and expense review looks like one service account, and you cannot tell which user triggered it. Scalekit resolves the credential of the actual user who triggered the agent, never a shared bot.
// shared key
audit → bot_service_account

// scalekit
audit → user_abc ✓
02.
Authentication is not authorization
03.
Multi-tenancy is architectural
04.
Breathe HR today. Ten connectors tomorrow.
“Our agents act across Salesforce, Gong, Google Drive, and more, on behalf of every customer. Scalekit behind the scenes meant we can keep adding tools without ever rebuilding how credentials or tool calling work.”
Venu Madhav Kattagoni
Head of Engineering / Von
FAQs
Frequently Asked Questions
Does the agent access Breathe HR as the user or through a shared key?
As the user. Each user connects their own Breathe HR API key once, and Scalekit sends it with every call. Audit logs attribute every leave approval, record change, and expense review to that user, not a shared service account.
Where is the Breathe HR API key stored?
In Scalekit's managed AES-256 token vault, namespaced per tenant. To rotate it, the user reconnects with a new API key. Revocation is a single dashboard action. Credentials never appear in prompts, logs, or LLM context.
Can I limit what the agent does in Breathe HR?
Yes. Filter by tool name in listScopedTools to expose only what you want, for example the read tools without breathehr_leave_request_approve or breathehr_expense_claim_delete, which cannot be undone. Scalekit also enforces scope checks before every API call.
What happens when a user revokes Breathe HR access?
The connection is invalidated on the next tool call. Subsequent requests for that user fail closed with a clear error. Other users in the tenant remain unaffected. The event is logged for audit.
Can the agent see salary and bonus data in Breathe HR?
Yes, if you expose those tools. breathehr_salaries_list, breathehr_bonuses_list, and breathehr_benefits_list return pay records across the account, and the department and employee variants narrow them. Leave them out of toolNames for agents that should not see compensation.
Start in your coding agent
Up and running in one command
Install the Scalekit skill in your editor of choice. Connector, auth, tools, prompt, all wired up
Claude Code REPL
/plugin marketplace add scalekit-inc/claude-code-authstack
/plugin install agentkit@scalekit-auth-stack
Cursor Code REPL
# ~/.cursor/mcp.json
{
""mcpServers"": {
""breathehr"": {
""url"": ""https://mcp.scalekit.com/breathehr"",
""headers"": { ""Authorization"": ""Bearer $SCALEKIT_TOKEN"" }
}
}
}
Codex Code REPL
# ~/.codex/config.toml
[mcp_servers.breathehr]
url = ""https://mcp.scalekit.com/breathehr""
auth_env = ""SCALEKIT_TOKEN""
Copilot Code REPL
# .vscode/mcp.json
{
""servers"": {
""breathehr"": {
""url"": ""https://mcp.scalekit.com/breathehr"",
""type"": ""http""
}
}
}