> ## Documentation Index
> Fetch the complete documentation index at: https://docs.twine.se/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP server

> Connect Claude, Claude Code, or another AI assistant to your Twine data over the Model Context Protocol

Twine runs a [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server. Connect an AI assistant to it and the assistant can read your organization's Twine data on its own: employees, time reports, organizational units, system integrations, domain mappings, jobs, and flow runs. You can then ask it questions such as "who started last month?", "why did last night's Fortnox sync fail?", or "which property mapping sets the cost center?" and it looks the answer up instead of guessing.

The server is mostly read-only. A small set of tools can create, update, or delete domain mappings and sync triggers, and they work only when the role you connect with allows it.

| Environment | Server URL | Twine app |
| - | - | - |
| Production | `https://mcp.twine.se/mcp` | [app.twine.se](https://app.twine.se) |
| Stage | `https://mcp-stage.twine.se/mcp` | [app-stage.twine.se](https://app-stage.twine.se) |

The server speaks Streamable HTTP and accepts OAuth 2.1 with PKCE or a bearer token.

This page uses the production URL. To connect to stage, use the stage URL wherever the production one appears. Stage is a separate environment with its own organizations, roles, and tokens: you sign in to stage with your stage account, and a token or client ID from one environment does not work in the other.

## Before you start

* **You need to be an organization admin** in the Twine organization you are connecting. Granting an AI assistant access to HR and payroll data is an admin decision, so other users cannot complete the sign-in.
* **MCP access is switched off for every organization by default.** Signing in with OAuth switches it on for you when you approve the connection. If you connect with a service-account token instead, switch it on yourself: in Twine, open **Settings** > **Connected apps**, turn on **Enable MCP server access** under **MCP server access**, and save.
* **Each connection reaches one organization.** To use the same assistant with two organizations, add the server twice under different names and connect each one separately.

## Choose a connection method

| | Sign in with OAuth | Service-account token |
| - | - | - |
| Best for | A person using an assistant such as Claude or Claude Code | Automated agents, CI jobs, and partner products with no person signing in |
| Who signs in | A Twine organization admin, in the browser | Nobody. The token is pasted into the client's configuration |
| Needs a Twine account | Yes | No, only the admin who creates the token |
| Token lifetime | 1 hour, renewed automatically for up to 30 days of inactivity | 30 days, 90 days, or 1 year, chosen when the token is created |
| Renewal | Automatic | Create a new token before the old one expires |

## Option 1: Sign in with OAuth

Claude, Claude Code, and ChatGPT publish their own client details, which Twine accepts, so they connect without any setup on Twine's side. Other tools need a client ID from Twine support first; see [Get a client ID for another tool](#get-a-client-id-for-another-tool).

### 1. Add the server to your assistant

**Claude**

On Pro and Max plans, go to **Customize** > **Connectors** and choose **+ Add** > **Add custom connector**. On Team and Enterprise plans, an organization owner adds it under **Organization settings** > **Connectors** > **Add** > **Custom** > **Web**.

1. Enter a name, for example `Twine`, and the server URL `https://mcp.twine.se/mcp`.
2. Under **OAuth client**, keep **Use Claude's published identity**.
3. Finish adding the connector, then click **Connect** on it to sign in.

**Claude Code**

```bash theme={null}
claude mcp add --transport http twine https://mcp.twine.se/mcp
```

Then run `/mcp` inside Claude Code, select `twine`, and sign in in the browser window that opens.

**ChatGPT**

Add Twine as a custom connector with the server URL `https://mcp.twine.se/mcp` and OAuth sign-in. ChatGPT identifies itself to Twine, so leave any client ID and client secret fields empty, then sign in when ChatGPT opens the Twine page.

**Other clients**

Any MCP client that supports Streamable HTTP and OAuth with a pre-registered client works. [Get a client ID](#get-a-client-id-for-another-tool) first, then give the client:

* Server URL: `https://mcp.twine.se/mcp`
* Client ID: the value from Twine support
* Client secret: only if Twine registered your tool as a confidential client

The client discovers the rest from `https://mcp.twine.se/.well-known/oauth-protected-resource` and `https://mcp.twine.se/.well-known/oauth-authorization-server`. Twine supports the authorization code grant with PKCE (`S256`) and refresh tokens.

### 2. Approve the connection

Your assistant opens a Twine page in the browser. Sign in if you aren't already. For Claude, Claude Code, and ChatGPT, the page names the site that published the client's details, such as `claude.ai`. For a client that runs on your computer, such as Claude Code, it also warns you to approve only a connection you started yourself, because another program on your computer could use the same name. Then:

**1. Pick the organization**

The list shows the organizations where you are an admin. If you are an admin in only one, this step is skipped.

**2. Pick a role**

The assistant gets exactly the access of the role you pick, not your own. You can pick any role in the organization, so create a dedicated, narrower role for the assistant rather than handing it your admin role. See [Create a role for the assistant](#create-a-role-for-the-assistant).

**3. Approve**

Check the destination shown on the page, then click **Approve**. If MCP access was switched off for the organization, approving switches it on.

The browser returns you to your assistant, which is now connected. It renews its access by itself; if it hasn't been used for 30 days, sign in again.

### Get a client ID for another tool

Twine registers other AI tools by hand rather than letting them register themselves, because of the data on the other side of the connection. Every customer using the same tool shares one client ID, so if your tool is already registered, support can send you its ID straight away.

Email [support@twine.se](mailto:support@twine.se) and tell us:

1. Which AI tool you want to connect, and where you use it (for example in a browser, a desktop app, or a terminal).
2. The exact OAuth redirect URI the tool sends the browser back to, character for character, including any port and trailing slash.
3. Whether the tool is a public client that uses PKCE with no client secret, or a confidential client that stores a secret.

If you don't know these values, ask the assistant itself, in the same app you want to connect:

```text theme={null}
I want to connect you to a remote MCP server at https://mcp.twine.se that uses
OAuth 2.1. The server does not support Dynamic Client Registration, so its
operators have to register you manually and will issue me a client_id by hand.

Tell me, for this exact app and surface I am talking to you in right now:

1. Which product and surface is this (for example a browser, the desktop app,
   or a terminal CLI), and roughly which version?
2. The exact OAuth redirect URI (callback URL) you will send the browser back
   to, character for character, including scheme, any port, and any trailing
   slash. If it differs per platform or is a loopback URL with a random port,
   say so and list every value it can take.
3. Are you a public client using PKCE with no client secret, or a confidential
   client that can store a secret and send it on token requests?
4. Where exactly do I enter a client_id (and a client secret, if you need one)
   that was issued to me out of band?

Answer only from what you know about your own OAuth implementation. If you are
unsure of any value, say so instead of guessing, and point me at the setting or
the documentation page where I can read it off.
```

Forward its answer to support. If it hedges on the redirect URI, send us a link to the tool's documentation instead: the URI has to match exactly, and a near miss fails at sign-in.

> [!NOTE]
>
> None of these values are secret, and neither is the client ID we send back. Never send Twine support a token, a password, or a session cookie.

Twine accepts redirect URIs on `https://`, plus `http://localhost` and `http://127.0.0.1` for tools that run on your own machine. Wildcards are not accepted, so a tool that picks a random local port each time needs to be set to a fixed one.

## Option 2: Use a service-account token

A service-account token belongs to a role rather than to a person, so whoever runs the agent never needs a Twine account. A Twine admin creates the token and sends it over a one-time link.

**1. Create a role**

Follow [Create a role for the assistant](#create-a-role-for-the-assistant).

**2. Create a share link**

In **Settings** > **Roles**, open the role and click **Share token**. Give the token a name that says who uses it and for what, for example "Payroll audit agent", choose how long it stays valid under **Expires after**, and click **Generate share URL**. Copy the link and send it to the person setting up the agent.

**3. Reveal the token**

The recipient opens the link and clicks **Reveal secret**. The token is shown once, so they should copy it straight into the client's configuration or a secrets manager. The link stops working after that, and expires after 5 days if nobody opens it.

**4. Switch on MCP access**

If nobody in the organization has connected with OAuth yet, switch MCP access on under **Settings** > **Connected apps**. See [Before you start](#before-you-start).

Configure the client to send the token as a bearer header on every request:

**Claude**

When you add the custom connector, choose not to sign in, and under **Request headers** add `Authorization` with the value `Bearer <token>`.

**Claude Code**

```bash theme={null}
claude mcp add --transport http twine https://mcp.twine.se/mcp \
  --header "Authorization: Bearer <token>"
```

**Other clients**

Send `Authorization: Bearer <token>` on every request to `https://mcp.twine.se/mcp`.

> [!WARNING]
>
> Treat the token like a password. Anyone holding it can read whatever its role allows until it expires.

If the token is lost before anyone saved it, create a new share link; this issues a new token. To stop a token early, open the role in **Settings** > **Roles** and revoke the token in its token list. Requests using it are refused from then on.

## Create a role for the assistant

Whichever method you use, the assistant's access is set by a Twine role. The **MCP service account** preset creates one with the access the MCP tools need.

1. In Twine, open **Settings** > **Roles** and click **Quick start**.
2. Choose the **MCP service account** preset and give the role a name.
3. Choose **No access**, **Read**, or **Read + Write** for each family:
   * **Employees**: personnel records, including managers, contact details, and salary history
   * **Time reports**: reported hours and time off
   * **Integrations**: system integrations, domain mappings, and their property mappings
4. Optionally, with **Integrations** set to **Read + Write**, tick **Also allow delete** to let the assistant delete domain mappings and sync triggers. Deletion cannot be undone.
5. Create the role.

**Read + Write** covers creating and updating, never deleting. Jobs, flow runs, and organizational units are always readable, since the assistant needs them to explain what a sync did.

A role you build by hand works as well, but it needs read access to jobs, flow runs, and organizational units for the troubleshooting tools to work.

## Check the connection

Ask your assistant:

> Call `list_capabilities` and tell me what you can do in Twine.

It replies with what the connected role allows for each kind of data. If something you expected is missing, the role is the place to change it.

You can also check a token from the command line. A working token returns the server's details; a rejected one returns an error that names the reason:

```bash theme={null}
curl https://mcp.twine.se/mcp \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'
```

## What the assistant can do

Assistants discover the tools themselves; you don't need to name them. This overview shows what is in reach.

| Area | Tools |
| - | - |
| Orientation | `list_capabilities`, `explain_concept` |
| Systems and data model | `list_systems`, `get_common_domain_properties`, `get_system_domain_properties`, `list_data_engine_nodes`, `get_data_engine_node`, `list_converters`, `list_property_mapping_templates` |
| Organization and configuration | `list_organizations`, `get_organization`, `get_organization_properties`, `list_system_integrations`, `get_system_integration`, `list_domain_mappings`, `get_domain_mapping` |
| Troubleshooting | `list_jobs`, `get_job`, `explain_job_failure`, `list_flow_runs`, `get_flow_run`, `get_audit_trail` |
| Data | `list_employees`, `get_employee`, `list_time_reports`, `get_time_report`, `list_organizational_units`, `get_organizational_unit` |
| Changes | `upsert_domain_mapping`, `delete_domain_mapping`, `delete_sync_trigger`, `set_organization_property`, `delete_organization_property` |

A tool the role cannot use is left out of the assistant's tool list or refused with an explanation, so the assistant never sees data the role doesn't cover.

The server also tells the assistant how Twine stores data. Most fields are [dated properties](https://docs.twine.se/platform/data-model.md#dated-properties), a list of values over time where the first entry is the current one, and `list_employees` accepts a [dated property query](https://docs.twine.se/platform/data-model/dated-property-queries.md) to filter on them.

## Troubleshooting

> **"MCP is not enabled for your organization"**
>
> MCP access is switched off for the organization. Turn on **Enable MCP server access** under **Settings** > **Connected apps**, or sign in again with OAuth, which switches it on when you approve.
>
> Claude Code reports this as "needs authentication" and asks you to sign in again, even though your sign-in is fine. Switch MCP access on and reconnect.

> **"The supplied redirect\_uri does not match"**
>
> The tool sent a redirect URI that differs from the one Twine registered. URIs are compared exactly, so `https://example.com/cb` and `https://example.com/cb/` are different, and so are two port numbers. Find out the exact URI your tool uses and send it to [support@twine.se](mailto:support@twine.se) so it can be added.

> **The sign-in page says you can't authorize MCP access**
>
> You aren't an admin in any Twine organization. Ask an admin in your organization to connect, or to give you admin rights.

> **The assistant was disconnected and has to sign in again**
>
> Twine ends the connection if it hasn't been used for 30 days. It also ends it if an old, already-replaced refresh token is presented again, which is how Twine responds to a token that may have been copied. In both cases, sign in again.

> **"MCP server is temporarily disabled by Twine operations"**
>
> Twine has paused MCP access for maintenance or to contain an incident. Connections resume when Twine lifts the pause; nothing needs to change on your side.

> **The assistant can't see jobs, flow runs, or some data**
>
> The connected role doesn't allow it. Ask the assistant to call `list_capabilities` to see what the role permits, then widen the role or connect with a different one. Roles built by hand often lack read access to jobs, flow runs, and organizational units; the **MCP service account** preset includes them.

> **A service-account token stopped working**
>
> It has expired or been revoked. Create a new share link from the role, as in [Option 2](#option-2-use-a-service-account-token).

## Security

The assistant acts with the permissions of the role it is connected with, and every tool call is checked against that role before data is returned. Tokens are recorded by Twine and can be revoked individually. See [Security](https://docs.twine.se/platform/security.md) for how Twine authenticates and authorizes machine access.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.