# Code & repos

> Step-by-step connection and configuration for GitHub, GitLab, Azure DevOps, Bitbucket and CircleCI.

Source: https://triagic.com/docs/integrations/code

These let the agent *read* code, issues and merge requests while it investigates.

> **Note:** Reading repos is not the same as filing issues
>
> Filing a finished triage as a new issue is a separate, per-user connection made in the
> desktop app; see [Filing issues](/docs/desktop/issues). Nothing configured here can
> write.

## GitHub [#github]

`github` · runs GitHub's official server image via **Docker** · read-only is pinned on
via the server's own `GITHUB_READ_ONLY` mode, regardless of what else is configured.

Overview, prompts and the tool list: [/integrations/github](/integrations/github).

1. **Create a fine-grained personal access token.** GitHub → **Settings → Developer
   settings → Personal access tokens → Fine-grained tokens**.

   * **Repository access**: only the repositories the agent should see.
   * **Permissions**, all read-only: **Contents**, **Issues**, **Pull requests**, **Metadata**.

   For a token on an organization's repositories, an org owner may need to approve it.

2. **Confirm Docker is installed** on every member's machine. This integration reports
   degraded without it.

3. **For GitHub Enterprise Server, note the host and its CA.** Give the **Enterprise
   host** field the base URL only: `https://github.acme.internal`, with no path. The
   server appends the REST path (`/api/v3`) itself, and refuses a plain `http://` host so
   the token is never sent in the clear. An Enterprise Cloud data-residency host
   (`https://acme.ghe.com`) goes in the same field.

   If that host's certificate comes from a private CA, put an absolute path to the CA's
   PEM bundle in **CA certificate path**. It is mounted read-only into the container and
   becomes the trust store the server verifies against.

   > **Warning:** There is no “skip verification” option here
   >
   > The server image is a Go binary, and its only trust lever is the CA bundle. Upstream
   > was asked for a verification-disable switch and declined it, so the CA path is the
   > whole answer. Unlike the database integrations, there is no toggle to fall back to.

4. **Fill the form.**

   | Field                     | Required                                  | What to put                                                                                                                                                                                                                                                |
   | ------------------------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
   | **Personal access token** | yes                                       | `github_pat_…`. A classic PAT or a GitHub App **installation** token works in this same field; GitHub's REST API takes all three as the same bearer credential. App ID and private key are not collected: the server has no way to mint a token from them. |
   | **Toolsets**              | no, defaults `repos,issues,pull_requests` | Comma-separated GitHub toolsets. Whatever you type, the `context` toolset is always kept on: it owns the identity call used as the health check.                                                                                                           |
   | **Enterprise host**       | no                                        | Leave blank for github.com. Otherwise the base URL with its `https://` scheme and nothing after it.                                                                                                                                                        |
   | **CA certificate path**   | no                                        | Enterprise host behind a private CA only. An absolute path on the member's machine to that CA's PEM bundle.                                                                                                                                                |

5. **Verify.** Health check is `get_me`.

| If it reports                                                                   | It usually means                                                                                                          |
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `Bad credentials` / `401`                                                       | Expired, revoked or mistyped token.                                                                                       |
| `Resource not accessible by personal access token`                              | The token is valid but wasn't granted this repository or organization. Extend its repository access, or get org approval. |
| `x509: certificate signed by unknown authority`, `failed to verify certificate` | The Enterprise host's certificate isn't signed by a CA the container trusts. Set **CA certificate path**.                 |
| A missing-runtime error                                                         | Docker isn't installed or isn't running on that machine.                                                                  |

## GitLab [#gitlab]

`gitlab` · runs `@zereight/mcp-gitlab` via **npx** with read-only mode on · works with
gitlab.com and self-hosted.

Overview, prompts and the tool list: [/integrations/gitlab](/integrations/gitlab).

1. **Create an access token*&#x2A; with the &#x2A;*`read_api`** scope (GitLab → **Preferences →
   Access tokens**). `read_api` is enough for projects, issues and merge requests; `api`
   would grant writes the server is already refusing.

   A **project or group access token** works in the same field and reaches less: a
   personal token carries everything its owner can see, a project token only that
   project. GitLab's token header takes all three, so prefer the narrowest one that
   covers the repositories you want read. Project and group tokens are created with the
   `api` scope rather than `read_api`. Read-only mode is still enforced on this side.

2. **For a self-hosted instance behind a private CA,** put an absolute path to that CA's
   PEM bundle in **CA certificate path**. It is trusted in addition to the machine's own
   roots, for this integration's process only.

   Leave **Verify TLS certificate** on. Turning it off makes the connection accept any
   certificate the instance presents: the traffic is still encrypted, but nothing proves
   who's on the other end. It affects only the GitLab process Triagic spawns, never the
   rest of the app.

3. **Fill the form.**

   | Field                      | Required        | What to put                                                                                                                      |
   | -------------------------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------- |
   | **Access token**           | yes             | `glpat-…`, or a project/group access token.                                                                                      |
   | **API URL**                | no              | Self-hosted only, and it **must include the `/api/v4` suffix**: `https://gitlab.example.com/api/v4`. Leave blank for gitlab.com. |
   | **CA certificate path**    | no              | Absolute path on the member's machine to a PEM CA bundle.                                                                        |
   | **Verify TLS certificate** | no, defaults on | Turn off only for a self-signed instance you cannot supply a CA bundle for.                                                      |

4. **Verify.** Start-checked only. This server documents no zero-argument read tool, so
   the first real tool call is what proves the credential.

| If it reports                                                                        | It usually means                                                                                                                          |
| ------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `404` / `not found`                                                                  | Nearly always the API URL missing its `/api/v4` suffix.                                                                                   |
| `401` / `invalid token`                                                              | Expired token, or one without `read_api`.                                                                                                 |
| `unable to get local issuer`, `SELF_SIGNED_CERT…`, `UNABLE_TO_VERIFY_LEAF_SIGNATURE` | The instance's certificate isn't signed by a CA this machine trusts. Set **CA certificate path**, or turn off **Verify TLS certificate**. |

## Azure DevOps [#azure-devops]

`azure-devops` · runs `@azure-devops/mcp` via **npx** · Microsoft's own server.

Overview, prompts and the tool list: [/integrations/azure-devops](/integrations/azure-devops).

> **Info:** Read-only in two places
>
> The server has no read-only switch and ships create, update and queue tools. Triagic
> exposes only the read tools, and leaves out the two that can save a file onto the
> machine and the backlog tool that can reorder work items. Give the token Read scopes
> only and it can't write even if a tool slipped through.

1. **Create a personal access token.** In Azure DevOps, **User settings → Personal access
   tokens → New token**. Set **Organization** to the one you're connecting, pick **Custom
   defined**, and tick **Read** under Project and Team, Code, Work Items, Build, Wiki and
   Identity. Nothing else. Copy it; it's shown once.

2. **Fill the form.**

   | Field                     | Required | What to put                                                                    |
   | ------------------------- | -------- | ------------------------------------------------------------------------------ |
   | **Organization**          | yes      | The name from `https://dev.azure.com/acme`, so `acme`. A pasted URL works too. |
   | **Personal access token** | yes      | Just the token. Triagic encodes it the way the server expects.                 |

3. **Verify.** The health check lists one project, which tests the organization name and
   the token together.

Azure DevOps Services only. Azure DevOps Server (on-premises) isn't reachable through
this server.

| If it reports                        | It usually means                                                                               |
| ------------------------------------ | ---------------------------------------------------------------------------------------------- |
| `Failed to find api location`        | The organization name is wrong, or a full URL with extra path landed in it.                    |
| `Failed request: (401)` / `TF400813` | The token expired, was revoked, or was created for a different organization.                   |
| `403`                                | The token is missing a Read scope for what the agent asked. Recreate it with the scopes above. |

## Bitbucket [#bitbucket]

`bitbucket` · runs `@tugudush/bitbucket-mcp` via **npx** · read-only by construction: the
server only sends GET requests and has no write tools.

Overview, prompts and the tool list: [/integrations/bitbucket](/integrations/bitbucket).

1. **Create an API token with scopes.** At [id.atlassian.com](https://id.atlassian.com/manage-profile/security/api-tokens),
   choose **Create API token with scopes**, set an expiry, pick **Bitbucket**, then tick only
   read scopes: account, workspace, project, repository, pull request, pipeline and issue.
   Copy it; it's shown once. App passwords stopped working in June 2026, so an old one won't do.

2. **Fill the form.**

   | Field                       | Required | What to put                                                                  |
   | --------------------------- | -------- | ---------------------------------------------------------------------------- |
   | **Atlassian account email** | yes      | The email you sign in to Atlassian with. Your Bitbucket username won't work. |
   | **API token**               | yes      |                                                                              |

3. **Verify.** The health check reads your own Bitbucket account, which tests the email and
   token together and needs the account read scope.

Bitbucket Cloud only. Bitbucket Data Center isn't reachable through this server.

| If it reports      | It usually means                                                                                            |
| ------------------ | ----------------------------------------------------------------------------------------------------------- |
| `401 Unauthorized` | The email and token don't match, the token expired, or it's an app password or a token made without scopes. |
| `403 Forbidden`    | The token is missing a read scope. Recreate it with the scopes above.                                       |
| `404 Not Found`    | The workspace or repository slug is wrong, or this account can't see it.                                    |

## CircleCI [#circleci]

`circleci` · runs `@circleci/mcp-server-circleci` via **npx** · read-only by an
allowlist: pipeline triggers, reruns and rollbacks stay out.

Overview, prompts and the tool list: [/integrations/circleci](/integrations/circleci).

Covers failed build logs, latest pipeline status, job test results, flaky tests,
artifacts and deploy component versions, so a ticket can be tied to the CI failure
behind it.

> **Warning:** The token can't be scoped
>
> A CircleCI personal API token carries its user's full access, so **the allowlist is
> the boundary**. Mint the token from a user who can see only the projects you want
> reachable.

1. **Create a personal API token.** CircleCI → **User Settings → Personal API Tokens**.
   A project API token won't work.

2. **Follow the projects.** The server finds projects through the list the token's user
   follows, and the health check fails when that list is empty.

3. **Fill the form.**

   | Field                  | Required | What to put                                                                                                |
   | ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------- |
   | **Personal API token** | yes      | `CCIPAT_…`                                                                                                 |
   | **Server URL**         | no       | Only for CircleCI Server (self-hosted), e.g. `https://circleci.example.com`. Leave blank for circleci.com. |

4. **Verify.** Health check lists the projects the token's user follows.

| If it reports                    | It usually means                                                             |
| -------------------------------- | ---------------------------------------------------------------------------- |
| `401` / `Invalid token provided` | Not a personal token, or a CircleCI Server token without the Server URL set. |
| `No projects found`              | The token works but its user follows no projects.                            |
| `404`                            | The user can't see that project, or the project slug is wrong.               |
| `ENOTFOUND` / `getaddrinfo`      | The Server URL doesn't resolve.                                              |
