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

# MCP connectors

> Give the agent scoped access to Notion or Confluence.

An MCP connector lets the agent read an internal system from inside the
sandbox. Enabling one is a policy change: Airlock stores the credentials outside
the repo, allowlists only that connector's domains, and registers the server so
the agent picks it up.

```sh theme={null}
airlock setup mcp
```

## Available connectors

<CardGroup cols={2}>
  <Card title="Notion" icon="book">
    Notion workspace access via `notion-mcp-server`.

    **Needs:** an integration token from
    [notion.so/profile/integrations](https://www.notion.so/profile/integrations)

    **Allows:** `api.notion.com`
  </Card>

  <Card title="Confluence" icon="building">
    Atlassian Confluence access via `mcp-atlassian-confluence`.

    **Needs:** site name, account email, and an API token from
    [id.atlassian.com](https://id.atlassian.com/manage-profile/security/api-tokens)

    **Allows:** `<your-site>.atlassian.net`
  </Card>
</CardGroup>

Both server binaries are preinstalled in the `airlock/base` image, so there is
nothing to install inside the sandbox.

## What setup writes

`airlock setup mcp` prompts for each credential (token input is hidden) and
then writes to exactly three places:

<Steps>
  <Step title="Credentials → ~/.airlock/secrets.toml">
    Stored outside every repo, keyed by connector name, with file mode `0600`.
    Credentials are never written into the repo.
  </Step>

  <Step title="Enable flag → .airlock.toml">
    Adds the connector to `[mcp] enable` so the sandbox knows to wire it up.
  </Step>

  <Step title="Server registration → .mcp.json">
    Adds the server command under `mcpServers` so Claude Code auto-detects it.
    No credentials go in this file — the server inherits its environment from
    the sandbox.
  </Step>
</Steps>

Then run the agent and the tools are available:

```sh theme={null}
airlock claude
```

## How credentials reach the server

Nothing is baked into `.mcp.json`. At sandbox start, Airlock reads the stored
secrets and injects them as environment variables that the stdio MCP server
reads:

| Connector    | Stored key | Injected as            |
| ------------ | ---------- | ---------------------- |
| `notion`     | `token`    | `NOTION_TOKEN`         |
| `confluence` | `site`     | `ATLASSIAN_SITE_NAME`  |
| `confluence` | `email`    | `ATLASSIAN_USER_EMAIL` |
| `confluence` | `token`    | `ATLASSIAN_API_TOKEN`  |

If a credential is missing, Airlock prints a warning naming the connector and
the missing field, and starts the sandbox without it rather than failing.

## Domains are derived, not guessed

Each connector declares the domains it needs, and Airlock adds only those to the
egress allowlist. Confluence declares `{site}.atlassian.net`, and the `{site}`
placeholder is filled in from your stored credential — so the allowlist ends up
containing your specific site, not all of Atlassian. A domain whose placeholder
cannot be resolved is dropped rather than allowed broadly.

## Enabling by hand

You can skip the prompts and edit policy directly:

```toml .airlock.toml theme={null}
[mcp]
enable = ["notion"]
```

The credentials still have to exist in `~/.airlock/secrets.toml` — run
`airlock setup mcp` at least once per connector, or write the file yourself.

<Warning>
  If `.airlock.toml` already has an `[mcp]` section that does **not** list this
  connector, `airlock setup mcp` stops and asks you to add the name to the
  existing `enable` list by hand.

  It aborts at that point, so only the credentials have been saved —
  `.mcp.json` is **not** written. After editing the `enable` list, either add
  the server to `.mcp.json` yourself or re-run `airlock setup mcp`, which now
  sees the connector already enabled and continues to the registration step.

  (If the connector is already in the list, setup proceeds normally and simply
  leaves `.airlock.toml` untouched.)
</Warning>
