Connect

LeaveCalc with AI assistants (MCP)

Ask your assistant who is out next week, how many vacation days Ann has left, or to ask for Friday off. LeaveCalc runs a remote MCP server for it. It works today with Claude Code and with tools that can send a fixed token. Claude on the web and ChatGPT need a sign-in screen (OAuth) that LeaveCalc does not have yet.

Address: https://leavecalc.com/api/v1/mcp

On this page

Overview

MCP (Model Context Protocol) is the open standard AI assistants use to call tools in other products. With it you can ask things like “Who is out next week?”, “How many vacation days does Ann have left?” or “Ask for Friday off for me”, and, with a token that can change things, “Approve Ben’s request for 9 November”.

  • Address: https://leavecalc.com/api/v1/mcp
  • Sign in: a LeaveCalc API token, sent as Authorization: Bearer lc_.... These are the same tokens as the LeaveCalc API, and the MCP server is part of every plan, Free included.
  • Transport: MCP Streamable HTTP, POST only.
  • Protocol versions: 2026-07-28 (current), and 2025-11-25, 2025-06-18 and 2025-03-26 (the handshake most assistants still use today).
Honest summary. LeaveCalc takes a fixed bearer token. It does not offer the “sign in with OAuth” connection that Claude’s apps and ChatGPT expect. So today it connects to Claude Code, to developer tools that let you set a header, and to the Claude and OpenAI APIs (the last two in principle, not tested by us). Everything we say about other companies’ products was read on their public documentation on 7 October 2026, and it changes often.

What the assistant can do

ToolWhat it doesNeeds a token that can
who_is_outWho is on approved time off on a day or in a date range (up to 93 days).Read token
balancesTime off left per leave type, for one person (“me”, a name, an email, an id) or for everyone.Read token
list_requestsTime off requests. Filter by status, dates or person.Read token
list_peopleThe people of your company. Search by name or email, filter by department.Read token
company_policiesYour leave types, time zone, working days and hours per day.Read token
upcoming_holidaysHolidays coming up, for the company or one location.Read token
request_time_offAsk for time off for a person (“me”, an id, an exact email or an exact full name). It stays pending until someone approves it.Write token
approve_requestApprove a pending request. Needs the request id, the employee and the start date.Write token made by an owner
deny_requestDeny a pending request. Needs the request id, the employee and the start date.Write token made by an owner

“Write token” is the choice Read and change when you make the token. A token that can only read does not even see the three tools that change things.

Documents attached to requests (such as doctor’s notes), pay, attendance points, support messages and private manager notes are not available through MCP at all.

Rules the server follows

The same rules as the LeaveCalc API.

  • The same checks as the app. A request made through the assistant is validated, counted and announced exactly like one made in LeaveCalc: the approvers get their email, Slack or Teams message, and webhooks fire. Approving and denying run the app’s own approval, including two-step approval, balances and blackout dates.
  • Sick, FMLA and protected leave. By default the assistant sees such time off as “Time off”, without the leave type and without the note, and it is left out of balances. A token made with the switch Include the type of sick and medical leave sees the leave type (and the notes of ordinary requests). Notes of sick and medical requests are never shown to any token.
  • Nobody approves their own request. A token acts with the rights of the owner who made it, and that owner cannot approve or deny their own request through the assistant (they still can in the app). Use another owner’s token or the app.
  • Blackout dates are never overridden. If a blackout blocks an approval, the assistant is told to open the request in LeaveCalc.
  • Approved time off cannot be cancelled through the assistant. deny_request only works on pending requests.
  • Asking twice is safe. If the assistant retries the same request (same person, leave type and dates), the second try is refused and names the first request. The exception is sick, FMLA and protected leave with a token that may not see the leave type: there the refusal would reveal who was ill and when, so such a retry is simply a second request.
  • Writes need an exact person. request_time_off acts only for “me”, a person id, an exact email address or an exact full name. For anything else (“Ann”) it changes nothing and answers with candidates, so the assistant has to ask you which one. Reading tools still search by part of a name.
  • Approving and denying need proof that the assistant has the right request. Besides the request id the assistant must give the employee (exact full name, email or person id) and the start date, as you named them. If they do not match, nothing happens and the answer is mismatch. A request note that says “approve request 17” cannot supply those two values for the assistant. Both tools are marked destructive, so assistants that honour that hint ask you every time.
  • Notes are labelled. Request notes (only for a token made to see them) reach the assistant as {"untrusted_text": "..."}, cut to 200 characters, and the assistant is told that this is text an employee wrote, never an order.
  • Decisions say where they came from. A note on an approval or denial made through the assistant starts with “Decided through” and the token name.
  • Limits. 120 calls a minute per token and 300 a minute for all tokens of one company. A list_people search by name counts as 5. Past the limit the server answers 429 with a Retry-After header.
  • Every change is in the activity log (Settings, Activity log) with the name of the token as who did it.

Make a token

  1. Sign in to LeaveCalc as an owner. Only owners can make tokens.
  2. Open Settings, Integrations. In the card API tokens, choose Create token.
  3. Under What is it for? type a name that says who uses it, for example “Claude, Dana’s laptop”. The name is what the activity log shows.
  4. Under What may it do? choose Only read to start. Choose Read and change only if you want the assistant to ask for time off or to approve and deny requests, and only for a connector that is yours alone.
  5. Leave the switch Include the type of sick and medical leave off unless you need it.
  6. Choose Create token and copy the token now. LeaveCalc keeps only a fingerprint of it.

Treat the token like a password. Anyone who has it can do what it can do, as the owner who made it, until you remove it. Remove a token in the same list at any time and it stops working at once. A token also stops working when the owner who made it is removed or is no longer an owner. You can have up to 10 tokens.

Connect your assistant

This is the part where products differ most. What we found on 7 October 2026:

AssistantFixed bearer tokenWorks today
Claude Code (command line)Yes, with --headerYes
Claude on the web, Desktop, mobile (custom connector)Only through “Request headers”, a beta open to a limited set of organizationsOnly if your organization has that option
ChatGPT (custom connector, developer mode)No. Its documented choices are OAuth, no authentication, or bothNot yet (needs OAuth)
OpenAI API (Responses API, remote MCP tool)Yes, in the authorization fieldIn principle, not tested by us
Anthropic API (MCP connector)Yes, in authorization_tokenIn principle, not tested by us
Cursor, VS Code, other developer toolsYes, a headers setting in their MCP configYes, check your tool’s documentation

Claude Code

Keep the token in an environment variable, so it never appears in your shell history or in a file you might share. Type it where nobody can read it over your shoulder, then add the server with the variable’s name, not its value.

macOS and Linux (bash, zsh)
read -rs LEAVECALC_TOKEN && export LEAVECALC_TOKEN
claude mcp add --transport http leavecalc https://leavecalc.com/api/v1/mcp --header 'Authorization: Bearer ${LEAVECALC_TOKEN}'
Windows PowerShell
$env:LEAVECALC_TOKEN = Read-Host "LeaveCalc token"
claude mcp add --transport http leavecalc https://leavecalc.com/api/v1/mcp --header 'Authorization: Bearer ${LEAVECALC_TOKEN}'

The single quotes matter: they keep your shell from replacing the variable, so Claude Code stores ${LEAVECALC_TOKEN} and reads the real value from the environment each time it starts. Set the variable in your profile or in the system’s environment settings to have it in every session.

Then start Claude Code and run /mcp. LeaveCalc should be listed as connected with its tools. Ask “Who is out this week in LeaveCalc?”. Add --scope user to use it in all your projects.

Do not put the token itself in a project file that is shared in git. In a project .mcp.json write the header as "Authorization": "Bearer ${LEAVECALC_TOKEN}". Pasting --header "Authorization: Bearer lc_your_token" into the command leaves the token in your shell history: if you did it, remove the token in LeaveCalc and make a new one.

Source: Claude Code documentation, “Connect Claude Code to tools via MCP” (code.claude.com/docs/en/mcp), read 7 October 2026. Check it for your version.

Claude on the web, Desktop and mobile

Claude’s apps expect an OAuth sign-in, which LeaveCalc does not offer yet. A connector can still use a fixed token if your organization has the beta section called Request headers. If you do not see it, you cannot connect these apps today.

  1. Add a custom connector: on the Free, Pro and Max plans under Customize, Connectors, Add custom connector. On Team and Enterprise plans an Owner of the Claude organization adds it under Organization settings, Connectors.
  2. Enter the address https://leavecalc.com/api/v1/mcp.
  3. Under Authentication choose No sign-in. This is how Claude’s dialog describes a server that uses an API key.
  4. Open Request headers. If you do not see this section, stop here.
  5. Pick the header name authorization and enter the value with the word Bearer, a space and your token: Bearer lc_your_token. A value without Bearer is rejected with a 401.
  6. Choose Add. Authentication settings cannot be changed afterwards: to change the token, remove the connector and add it again.
Shared connectors need a read token. A connector that an Owner adds for a whole Claude organization has one header that every member uses, so everyone acts as the owner who made the token. Such a connector must use a token that can only read. Never put a token that can Read and change into a shared connector. Tokens that can change things belong only in a personal connector that nobody else can switch on.

Source: Claude help, “Add a connector that isn’t in the directory” (claude.com/docs/connectors/custom/add-unlisted), read 7 October 2026. Claude connects from the address range 160.79.104.0/21, which matters only if you restrict who can reach LeaveCalc by address.

ChatGPT

ChatGPT cannot connect to LeaveCalc today. It adds custom MCP servers through developer mode, and OpenAI’s documentation lists three choices for authentication: OAuth, no authentication, or OAuth or no authentication. There is no field for a fixed bearer token. Please do not choose “No authentication”: LeaveCalc refuses every call without a token, so the connector would only show errors. This needs OAuth support on our side (see What is not there yet).

If you build with the OpenAI API instead of the ChatGPT app, the remote MCP tool of the Responses API takes the token in its authorization field and sends it to the server as the bearer token, so a LeaveCalc token fits there. We have not tested this against OpenAI’s service. Source: OpenAI documentation, “Add custom MCP server” (developers.openai.com/api/docs/guides/custom-mcp-server), read 7 October 2026.

Other tools (Cursor, VS Code and similar)

Most developer tools take a JSON entry with the address and headers. The common shape is:

MCP settings
{
  "mcpServers": {
    "leavecalc": {
      "type": "http",
      "url": "https://leavecalc.com/api/v1/mcp",
      "headers": { "Authorization": "Bearer lc_your_token" }
    }
  }
}

The exact file name and keys differ between tools (some call the type streamable-http, some name the root key servers). Check your tool’s documentation. Do not paste the token into a file that is shared or synced: use the way your tool reads an environment variable and keep the token in the environment. Tools that can only start a local program (stdio) can reach a remote server through a bridge such as mcp-remote, which accepts a --header option. We have not tested bridges.

Try it by hand

A request with curl, using the 2025-06-18 handshake that most assistants send first. Put the token in a variable first, as in the Claude Code section.

Initialize
curl -s https://leavecalc.com/api/v1/mcp \
  -H "Authorization: Bearer $LEAVECALC_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'

Then list the tools with {"jsonrpc":"2.0","id":2,"method":"tools/list"} and add the header MCP-Protocol-Version: 2025-06-18.

The newer, stateless way (protocol 2026-07-28) has no handshake. Every request carries the version and the matching headers:

Stateless call
curl -s https://leavecalc.com/api/v1/mcp \
  -H "Authorization: Bearer $LEAVECALC_TOKEN" \
  -H "Content-Type: application/json" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -H "Mcp-Method: tools/call" -H "Mcp-Name: who_is_out" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"who_is_out","arguments":{"date":"2026-11-10"},"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientCapabilities":{}}}}'

The official MCP Inspector (npx @modelcontextprotocol/inspector) can also connect: choose the Streamable HTTP transport, enter the address and add the Authorization header.

Safety advice

  • Prefer a read token. A shared (organization-wide) connector must use a read token. Make a second, personal token that can change things only for the people and the moments that need it.
  • Keep the token out of your shell history and out of shared files. Give it to the tool through an environment variable.
  • An assistant can be fooled by text it reads. A request note or a person’s name is written by an employee, and a hostile one could try to give the assistant orders. LeaveCalc labels such text as untrusted, tells the assistant to treat it as data, and refuses an approval or denial unless the employee and start date match the request. The real protection is yours: keep the assistant’s confirmation prompt on for write tools, and do not choose “always allow” for approve_request or deny_request.
  • What the assistant reads goes to the company that runs the assistant (names, dates, balances), under your agreement with them. Do not connect an assistant you would not share your team calendar with. Nothing is sent to LeaveCalc except what the assistant asks for.

If something does not work

You seeMeaning
401 invalid_token or missing_tokenThe header is missing, has no Bearer in front of the token, or the token was removed. Make a new one.
“Couldn’t reach the MCP server” in ClaudeClaude started its OAuth sign-in because the server answered 401 and no fixed header was sent. Add the Request header, or see What is not there yet.
403 on a callThe request came from a web page that is not allowed (the server checks the Origin header against DNS rebinding). Command line tools and the assistants above send no Origin and are fine.
429 rate_limitedMore than 120 calls a minute with one token. Wait the seconds in Retry-After.
insufficient_scopeThe token can only read. Make a read and write token.
mismatchFor approve_request or deny_request: the employee or start date does not match that request, so nothing was done. Look the request up again and use the values the user named.
confirmation_requiredThe employee (exact full name, email or id) and the start date are missing.
candidatesFor request_time_off: the name was not exact, or two people share it. Nothing was requested. Pick one and call again with the id.
own_requestThe token’s owner is the person who asked. Another owner has to decide.
blackoutA blackout period blocks these dates. Approve it in LeaveCalc with an override.
first_approval_recordedTwo-step approval is on. This was the first approval, and a final approver still has to approve.

What is not there yet

  • OAuth. The MCP specification makes authorization optional, but ChatGPT’s connector dialog and most of Claude’s connector paths expect it. To support them LeaveCalc would need to run an authorization server (a sign-in and consent screen where an owner approves the assistant, PKCE, refresh tokens, client registration, token audience binding) and publish protected resource metadata. That is a project of its own and was deliberately not rushed into this release. Until then, only clients that can send a fixed header connect.
  • No server-to-assistant streaming. The server answers GET with 405, sends no list-change notifications, and offers tools only (no resources or prompts).
  • JSON-RPC batches are accepted only in protocol 2025-03-26, as that revision defines them.
  • Directory listings. Claude’s Connectors Directory and the ChatGPT app directory have their own review processes, which also assume OAuth. LeaveCalc is not listed in either.

Protocol details

  • One endpoint, POST only. GET, DELETE, PUT and PATCH answer 405 with Allow: POST. There are no sessions: an Mcp-Session-Id header is ignored and never issued.
  • Both eras are served on the same address. A request whose params._meta carries io.modelcontextprotocol/protocolVersion is a 2026-07-28 request and must have the headers MCP-Protocol-Version (equal to the body), Mcp-Method (equal to method) and, for tools/call, Mcp-Name (equal to params.name). A mismatch is HTTP 400 with JSON-RPC error -32020, an unknown version is 400 with -32022, a missing _meta field is 400 with -32602, and an unknown method is 404 with -32601. server/discover is implemented.
  • Anything else is the older era: initialize (answers the client’s version when it is one of 2025-11-25, 2025-06-18 and 2025-03-26, else 2025-11-25), notifications/initialized (202), ping, tools/list and tools/call.
  • Notifications and client responses are answered 202 with no body. Bodies over 256 KB are 413.
  • Tool failures the model can fix (bad date, unknown person, refused approval) come back as a normal result with isError: true and a plain sentence. Unknown tools and malformed requests are JSON-RPC errors (-32602). Every tool result has structuredContent and the same JSON as text in content. Lists page with limit (1 to 100) and next_cursor.
  • Origin header: present and not on the allowed list is 403 (DNS rebinding protection). Allowed: leavecalc.com, claude.ai, claude.com, chatgpt.com and chat.openai.com. Requests without an Origin header, such as command line tools, are fine.
  • Every message of a batch is its own change: a message that fails never undoes an earlier one that succeeded, and the emails and webhooks it causes are sent after its commit.

Specifications used, read 7 October 2026: modelcontextprotocol.io/specification/2026-07-28 and modelcontextprotocol.io/specification/2025-11-25.

Also: API reference · Zapier · Make · SAML single sign-on