# MCP server

The TunnelHQ MCP server lets an AI assistant such as Claude, ChatGPT, Cursor, or VS Code work with TunnelHQ directly. Ask it to test a config, add a monitor, or check on an incident, and it does the work through the same API you would use.

There are two ways to connect:

| | Sign in | API key |
| --- | --- | --- |
| Where it runs | Hosted by TunnelHQ at `https://mcp.tunnelhq.com/mcp` | On your machine, started by `npx` |
| How it signs in | You sign in to TunnelHQ and approve the connection. No key is copied. | A `TUNNELHQ_API_KEY` in your client's config |
| Clients | Claude, Claude Code, ChatGPT, Cursor, VS Code, Windsurf, and any client with Streamable HTTP and OAuth | Any client that starts a local MCP server, such as Cline |
| What it can do | Read, or read and write. It never deletes. | Every tool, narrowed by the [environment variables](#environment-variables) |

Both need a workspace on a plan with API access, which is Starter and above.

## Connect by signing in

[Developers → AI assistants](https://app.tunnelhq.com/api/ai) in the dashboard shows the server address, these steps, a few prompts to try, and the assistants connected to the workspace.

<Tabs syncKey="mcp-sign-in">
  <TabItem label="Claude">
    <Steps>

    1. In Claude, open **Customize**, then **Connectors**.
    2. Choose **Add**, then **Add custom connector**.
    3. Name it TunnelHQ and paste `https://mcp.tunnelhq.com/mcp`. Choose **Continue**, then **Add**.
    4. Choose **Connect** and sign in to TunnelHQ in the tab that opens.

    </Steps>

    On a Claude Team plan, only an Owner can add a connector. Members then choose **Connect**.
  </TabItem>
  <TabItem label="Claude Code">
    <Steps>

    1. Add the server:

       ```bash title="Add TunnelHQ to Claude Code"
       claude mcp add --transport http tunnelhq https://mcp.tunnelhq.com/mcp
       ```

    2. In Claude Code, type `/mcp`, choose **tunnelhq**, and choose **Authenticate**. A browser tab opens for the sign-in.

    </Steps>
  </TabItem>
  <TabItem label="Cursor">
    **Add to Cursor** on the AI assistants page adds the server. Cursor then shows **Needs login** next to TunnelHQ: choose it and sign in.

    Without the button, add this to `~/.cursor/mcp.json`:

    ```json title="~/.cursor/mcp.json"
    {
      "mcpServers": {
        "tunnelhq": {
          "url": "https://mcp.tunnelhq.com/mcp"
        }
      }
    }
    ```
  </TabItem>
  <TabItem label="VS Code">
    **Add to VS Code** on the AI assistants page adds the server. VS Code asks whether you trust it: choose **Trust**, then sign in.

    Without the button, run **MCP: Add Server**, choose **HTTP**, and paste `https://mcp.tunnelhq.com/mcp`.
  </TabItem>
  <TabItem label="ChatGPT">
    <Steps>

    1. Open **Settings**, **Connectors**, **Advanced**, and turn on **Developer mode**.
    2. Choose **Create**. Name it TunnelHQ, paste `https://mcp.tunnelhq.com/mcp`, and set **Authentication** to **OAuth**.
    3. Choose **Create** and sign in.

    </Steps>

    Developer mode needs a ChatGPT plan that includes it. Check ChatGPT's current requirements.
  </TabItem>
  <TabItem label="Windsurf">
    <Steps>

    1. Open the MCP config file from the Cascade panel.
    2. Add this and save:

       ```json title="Windsurf MCP config"
       {
         "mcpServers": {
           "tunnelhq": {
             "serverUrl": "https://mcp.tunnelhq.com/mcp"
           }
         }
       }
       ```

    3. Sign in when Windsurf asks.

    </Steps>
  </TabItem>
  <TabItem label="Other">
    Use `https://mcp.tunnelhq.com/mcp` with Streamable HTTP and OAuth. If your client only takes a key, [run the server with an API key](#run-the-server-with-an-api-key) instead.
  </TabItem>
</Tabs>

### Approving the connection

The sign-in opens a TunnelHQ page, **Connect *app* to TunnelHQ**, that names the app and asks three things:

- **Workspace**: starts on the one you were last in. A workspace on a plan without API access is marked **(no API access)**, and no assistant can connect to it.
- **Project**: **All projects**, or one project.
- **Access**: **Read and write**, or **Read only**. If your role in the workspace is Viewer, the connection can only read.

Choose **Allow** to connect, or **Cancel**.

If TunnelHQ doesn't recognise the app, the page shows it by its web address with a warning, and **Allow** stays off until you tick **I started this and I trust *address***. Only tick it if you started the connection yourself.

### What a connected assistant can do

- **Read only** sees monitors, Uptime checks and heartbeats, results, incidents, subscriptions, usage, and the workspace's projects.
- **Read and write** can also test a config or link, create and edit monitors, Uptime checks, heartbeats and subscriptions, run a check now, retest an incident's monitor, acknowledge an incident, and sync a subscription.
- Neither can delete anything, or touch API keys, billing, or team members. Do those in the dashboard.

Testing counts as a change, because each test uses the workspace's on-demand test allowance. Your role in the workspace still applies on top, as it does for an API key. On a read-only connection, a tool that changes something answers "This connection is read only. Reconnect with "Read and write" to change anything."

A signed-in assistant sees 29 of the server's [tools](#tools). The five it doesn't see are `delete_monitor`, `bulk_delete_monitors`, `delete_subscription`, `list_api_keys`, and `revoke_api_key`.

When the connection reaches only one project, tools use it without being told, and searching across the workspace's other projects is refused. Otherwise the assistant names a project in its calls, and `list_projects` shows the choices.

### Managing connections

The **Connected** list on [Developers → AI assistants](https://app.tunnelhq.com/api/ai) shows each connection with:

- the app;
- its access;
- its project, or **All projects**;
- who connected it (Owners and Admins see everyone's connections, others see their own);
- when it was last used.

**Revoke** asks first, then ends that app's access to the workspace at once. Anything it already created stays, and you can connect it again later. A connection that goes unused for 90 days ends by itself.

### Prompts in the dashboard

On every plan except Free, the empty Tunnels and Uptime pages show a **Set it up with an AI assistant** card. Step 1 connects an assistant, and step 2 copies a prompt written for that page. The Tunnels prompt has the assistant read your VPN files, private keys included, to add them, so use it with an assistant you trust with those files. During onboarding, the "How would you like to add it?" step offers the same prompt under **Have the configs in a project? Show the prompt**.

## Run the server with an API key

This section describes MCP server 0.4.0, the current release. It runs on your machine and has every tool, including the ones that delete.

### Before you start

The MCP server authenticates with a TunnelHQ API key, available on Starter and above. Create one under **Developers → API Keys**.

:::tip[Setup with your key filled in]
The in-app [Install page](https://app.tunnelhq.com/api/install) shows these steps with your API key already filled in, with a tab for each client. It's the fastest way to connect.
:::

### Set up your client

If you use the [CLI](https://docs.tunnelhq.com/cli/), `thq mcp --client <claude|cursor|windsurf|cline> --apply` does this for you: it runs `claude mcp add` for Claude Code, or writes the JSON config for the other clients.

<Tabs syncKey="mcp-client">
  <TabItem label="Claude Code">
    <Steps>

    1. Add the server:

       ```bash title="Add the MCP server to Claude Code"
       claude mcp add tunnelhq --scope user \
         --env TUNNELHQ_API_KEY="thk_..." \
         -- npx -y https://tunnelhq.com/releases/mcp/latest/tunnelhq-mcp.tgz
       ```

    2. Check that it registered:

       ```bash title="Check that it registered"
       claude mcp list
       ```

    </Steps>
  </TabItem>
  <TabItem label="Cursor">
    Add the server to `~/.cursor/mcp.json`, or to `.cursor/mcp.json` at the root of a repository to use it in that project only:

    ```json title="~/.cursor/mcp.json"
    {
      "mcpServers": {
        "tunnelhq": {
          "command": "npx",
          "args": ["-y", "https://tunnelhq.com/releases/mcp/latest/tunnelhq-mcp.tgz"],
          "env": {
            "TUNNELHQ_API_KEY": "thk_..."
          }
        }
      }
    }
    ```
  </TabItem>
  <TabItem label="Windsurf">
    Add the server to `~/.codeium/windsurf/mcp_config.json`:

    ```json title="~/.codeium/windsurf/mcp_config.json"
    {
      "mcpServers": {
        "tunnelhq": {
          "command": "npx",
          "args": ["-y", "https://tunnelhq.com/releases/mcp/latest/tunnelhq-mcp.tgz"],
          "env": {
            "TUNNELHQ_API_KEY": "thk_..."
          }
        }
      }
    }
    ```
  </TabItem>
  <TabItem label="Cline">
    In VS Code, click the Cline icon, then the gear icon, then **MCP Servers**, and paste this configuration. Cline saves it to your profile, and you don't need to restart.

    ```json title="Cline MCP configuration"
    {
      "mcpServers": {
        "tunnelhq": {
          "command": "npx",
          "args": ["-y", "https://tunnelhq.com/releases/mcp/latest/tunnelhq-mcp.tgz"],
          "env": {
            "TUNNELHQ_API_KEY": "thk_..."
          }
        }
      }
    }
    ```
  </TabItem>
</Tabs>

### Environment variables

| Variable | Description |
| --- | --- |
| `TUNNELHQ_API_KEY` | Required. Your API key. |
| `TUNNELHQ_HOST` | API host. Defaults to `https://beta.tunnelhq.com`. |
| `TUNNELHQ_PROJECT_ID` | The project tools use when a call doesn't name one. |
| `TUNNELHQ_PROJECT_LOCK` | `1` to refuse every project except `TUNNELHQ_PROJECT_ID`. Requires `TUNNELHQ_PROJECT_ID`. |
| `TUNNELHQ_READ_ONLY` | `1` to hide every tool that makes changes, leaving the 18 read-only tools. |
| `TUNNELHQ_ENABLE_ADMIN` | `1` to add `revoke_api_key`. |
| `TUNNELHQ_NO_CERT_RESOLVE` | `1` to skip certificate lookups. For OpenConnect and IKEv2 configs given as an IP address, the server normally connects to that address from your machine to read the hostname from its TLS certificate. |

#### Safer setups

- To let an assistant look but not touch, set `TUNNELHQ_READ_ONLY=1`.
- To keep an assistant inside one project, set `TUNNELHQ_PROJECT_ID` and `TUNNELHQ_PROJECT_LOCK=1`.
- Leave `TUNNELHQ_ENABLE_ADMIN` unset unless the assistant needs to revoke keys.

### Updates

npx keeps the copy it first downloaded and doesn't check the release URL again, so an installed MCP server doesn't update itself. To get a newer version, run `thq mcp --client claude --update` (or `cursor`, `windsurf`, or `cline`) and restart your editor. It clears only TunnelHQ's cached copy. Without the [CLI](https://docs.tunnelhq.com/cli/), `rm -rf ~/.npm/_npx` does the same, but clears the cache of every npx package.

## Tools

The server has 33 tools, or 34 with admin tools enabled: 18 that only read, 15 that make changes, and 1 admin tool.

| Group | Tools |
| --- | --- |
| Testing | `test_vpn`, `test_batch` |
| Monitors | `list_monitors`, `get_monitor`, `create_monitor`, `update_monitor`, `delete_monitor`, `check_monitor`, `batch_check_monitors`, `bulk_update_monitors`, `bulk_delete_monitors`, `search_monitors` |
| Uptime checks | `list_checks`, `create_check`, `update_check` |
| Results | `get_monitor_history`, `list_recent_results`, `list_recent_failures` |
| Incidents | `list_incidents`, `get_incident`, `acknowledge_incident`, `retest_incident` |
| Subscriptions | `list_subscriptions`, `get_subscription`, `create_subscription`, `update_subscription`, `sync_subscription`, `delete_subscription` |
| Account | `whoami`, `list_organizations`, `list_projects`, `get_usage`, `list_api_keys`, `revoke_api_key` (admin only) |

With these, your assistant can:

- Test any VPN config, share link, or subscription URL and report whether it connects, including batches of tests run in parallel.
- Create, update, delete, and list monitors, and search monitors across every project the key can reach.
- Update or delete many monitors at once. `bulk_update_monitors` and `bulk_delete_monitors` default to a dry run, so the first call only previews what would change.
- List, create, and change [Uptime checks](https://docs.tunnelhq.com/uptime/): websites, keywords, ping, TCP ports, DNS servers, and heartbeats. Creating a heartbeat returns the address your job calls.
- Run on-demand checks and read results and history.
- List incidents, read one with its timeline, acknowledge it, and retest its monitor.
- Manage subscription URLs and trigger syncs.
- Check plan usage and quotas before running rate-limited operations.

Tools that take a project accept its name (case-insensitive; an unambiguous partial match works), its `prj_` slug, or its number.
