# MCP Server: A Practical Guide

> Connect Claude Code, Cursor, or Codex to your ZopNight account over MCP and ask about cloud cost, resources, schedules and recommendations in plain language.

Source: https://zop.dev/learn/mcp-server
Published: 2026-07-01 · Updated: 2026-08-05 · Author: avinash-gaurav · Tags: zopnight, learn, mcp-server, mcp, integrations

---

Connect Claude Code, Cursor or Codex to your ZopNight account. Ask about cloud cost, resources, schedules and recommendations in natural language, and the assistant reads live data instead of guessing.

An MCP server (Model Context Protocol) is a stateless proxy that exposes structured tools to an AI assistant. Zop's runs over **Streamable HTTP**: your client sends JSON-RPC 2.0 over HTTP POST and gets a single JSON response back, or a Server-Sent Events stream if it asks for one in its `Accept` header. It is not WebSocket based, which matters because the transport setting is the one thing clients get wrong.

One server covers both products. The same endpoint and the same token carry ZopNight's cost and resource tools and ZopDay's deploy, infrastructure and Kubernetes tools; you choose which you care about by what you ask, not by adding a second connection.

## The connection URL

ZopNight shows your server URL in two places in the app:

- **Settings → Organisation**, in the MCP Server section, once the toggle is on
- **Developer Settings**, on the screen where you create your token

Copy it from either one; that way you always get the right host for your environment. The blocks below call it `MCP_SERVER_URL`, and your token `MCP_PAT`.

## Step 1: Enable MCP for your organisation

MCP is enabled per organisation, and only an admin (a user with the Organisation Update permission) can turn it on.

1. Log in to ZopNight and open **Settings** from the sidebar
2. Click the **Organisation** tab
3. In the Organisation details card, scroll to the **MCP Server** section, below the created date
4. Toggle the switch to **ON**

The status badge changes from Inactive to Active, and the server URL appears. If you cannot see the toggle, you are not an admin on that organisation.

## Step 2: Create a Personal Access Token

The server authenticates with a personal access token, prefixed `zn_pat_`.

1. Click your profile avatar at the **bottom-left of the sidebar**
2. Select **Developer Settings**
3. Click **Create Token**
4. Enter a name, for example "Cursor" or "Claude Code"
5. Choose an expiry period
6. Click **Create Token**, then copy the token immediately

The token is shown once. Store it in your secret manager, not in a committed file.

A PAT carries your identity, not a narrower one. Every call resolves your live role at the moment it is made, so it can do exactly what you can do in the UI, no more and no less. Mint it as the person with the narrowest role that does the job.

## Step 3: Configure your client

All three use the same two values: the server URL and the token.

### Claude Code

```bash
claude mcp add zopnight MCP_SERVER_URL -t http -H "Authorization: Bearer MCP_PAT"
```

The `-t http` flag is required. Without it, the URL is treated as a command to run rather than a server to call. Note the URL and token are written literally, with no angle brackets: `<` and `>` are redirection operators in most shells and will break the command.

### Claude Desktop

Claude Desktop has no config block: `claude_desktop_config.json` takes only local, command-launched servers, so a remote URL there is ignored. Add it through **Customize → Connectors → Add custom connector**, then under **Request headers** add `Authorization` with the value `Bearer ` followed by your token. The value is sent exactly as typed, so the word `Bearer` and the space must be there. Custom connectors are in beta and roll out gradually.

### Cursor

Open **Customize → MCPs → New MCP Server**, then paste and save this config (`url` plus an `Authorization: Bearer` header):

```json
{
  "mcpServers": {
    "zopnight": {
      "url": "MCP_SERVER_URL",
      "headers": {
        "Authorization": "Bearer MCP_PAT"
      }
    }
  }
}
```

### Codex

Open **Settings → Plugins → MCPs → Add**. Set **Type** to **Streamable HTTP**, **Name** to `zopnight`, and **URL** to `MCP_SERVER_URL`. Under **Headers**, add a header with Key `Authorization` and Value `Bearer MCP_PAT` — use the Headers section, not the "Bearer token env var" field. Click **Save**.

### Devin

Devin has no config file: open **Settings → Configuration → MCP Servers → Add Custom**, then paste this block. The field is `url`:

```json
{
  "mcpServers": {
    "zopnight": {
      "url": "MCP_SERVER_URL",
      "headers": {
        "Authorization": "Bearer MCP_PAT"
      }
    }
  }
}
```

### Grok build

Grok build registers MCP servers from the terminal, the same way as Claude Code:

```bash
grok mcp add --transport http zopnight MCP_SERVER_URL --header "Authorization: Bearer MCP_PAT"
```

## Step 4: Confirm it works

Start a new session and ask your assistant:

```text
List my organisations
```

A working connection calls the `list_organisations` tool and returns your organisations by name. That is the check to run before you ask anyone for help, because it isolates the connection from everything else: `list_organisations` is the only tool that needs no arguments, and every other tool takes the `org_id` it returns.

If it fails, the usual causes are the transport flag, an expired token, or the organisation toggle still being off.

## What the assistant can read

The server exposes **165 read tools across both products** (part of a 289-tool catalogue — 165 read + 124 write; the write side is covered in the next section). Reads need no extra permission and are checked against your role, so an assistant sees exactly what you would see in the UI. The per-product docs pages count only their own product's tools, so their totals are smaller; `tools/list` is always the authoritative answer for a given token.

| Area | Covers |
| --- | --- |
| **Explore** | Organisations, cloud accounts, resources, teams, discovery status |
| **Cost** | Cost and savings summaries, per-resource and per-provider breakdowns, trends, history, snapshots, budgets, billing sync |
| **Optimize** | Recommendations and their savings, schedules, overrides, resource groups |
| **Operate** | Start and stop history, actions, scheduler events, provisioning jobs, services and their deploys |
| **Govern** | Tagging policies, smart tags, roles, users, audit logs, notification channels |
| **Diagnose** | Metrics, error detail, and the state behind a failed deploy or job |
| **Ship** | Projects, environments, services, infrastructure, deploy status |
| **Introspect** | What your own token can do, including `get_my_permissions` |

List tools forward the full filter and pagination set (provider, status, region, search, sort), so the assistant asks precise questions rather than pulling everything and filtering afterwards. Expensive aggregations are served from a short-TTL cache, so repeated questions in one session stay fast.

Your own list is narrower than the catalogue by design. Call `tools/list`, or ask the assistant what ZopNight tools it has, and what comes back is filtered to what your token and role actually allow. Nothing advertised there will fail with a permission error.

One hard boundary worth knowing before a security review: `get_service_config` returns a service's shape, including its environment variable **keys with every value redacted**. No tool reveals an env var value, at any level of write access, for any role.

## Read and write

Most of the surface **reads**. A smaller set **writes**: it changes a schedule, sets a budget, ships a deploy, provisions infrastructure.

How much an agent may change is one setting per organisation, **Write access**, in **Settings → Organisation**. The levels are cumulative: choosing one admits everything below it.

| Write access | Admits | For example |
| --- | --- | --- |
| **Read-only** | Nothing. Read tools only. | — |
| **Metadata only** | ZopNight's own records. No cloud state, no cost. | Budgets, recommendation status, smart-tag acceptance |
| **Reversible changes** | Bounded blast radius, may affect cost. | Schedules, overrides, tagging policies, service deploys, rollbacks and config |
| **Irreversible changes** | No undo, or incurs cost. | Start and stop resources, provisioning jobs, Kubernetes writes, every delete |

Some surfaces are excluded at every level and no setting adds them: roles and permissions, user management, organisation deletion, cloud-account deletion, credentials, and bulk actions.

Before you raise it, read one thing: enabling MCP write means any content in your cloud environment becomes a potential instruction to your agent. Resource names, tags and descriptions are strings other people can influence, and a read tool hands them to a model that can call write tools. The control that matters is how much authority the agent has, which is what this setting is.

## How the permissions actually resolve

Every check happens at the gateway on the way in, which is the same place the UI's own calls are checked.

1. The gateway validates the PAT and identifies your email
2. The assistant calls `list_organisations` to discover which organisations you belong to
3. The gateway confirms MCP is enabled for the organisation you asked about
4. It confirms you are a member of that organisation
5. It checks the call against your live role, and against the write tier if the tool changes something
6. Results come back as JSON

The MCP server owns no authorization logic of its own; the gateway decides, against the same policy table the UI's own calls resolve against. Because your role is read per request, revoking access in the app takes effect on the assistant's next tool call. Every write lands in the audit trail with a `source` of `mcp` and the tool that made it.

## Where to go next

Full client-by-client setup, the complete tool catalogue, and troubleshooting live in the docs, split by product: [ZopNight MCP server](https://zop.dev/docs/zopnight/integrations/mcp) for cost, resources and scheduling, and [ZopDay MCP server](https://zop.dev/docs/zopday/integrations/mcp) for projects, deploys, provisioning and Kubernetes. Both describe the same endpoint.

If you are evaluating ZopNight itself rather than the integration, the [platform comparison](https://zop.dev/compare/cloudhealth-vs-zopnight) covers how it differs from dashboard-first tools, and you can [book a demo](https://bookings.zop.dev/#/discover-zopdev) to see the estate side.

## Frequently asked questions

### Which transport does the Zop MCP server use?

Streamable HTTP. It speaks JSON-RPC 2.0 over HTTP POST and returns a single application/json response, or a Server-Sent Events stream when the client's Accept header asks for one. It is not WebSocket based. In Claude Code, pass -t http. A wrong transport setting is the most common reason a connection fails.

### Where do I find the server URL?

Two places in the app: Settings then Organisation, in the MCP Server section once the toggle is on; or Developer Settings, on the screen where you create the token. MCP is enabled per organisation by an admin, so the URL appears once the toggle is on.

### How is the MCP server authenticated?

A personal access token (zn_pat_*) sent as an Authorization Bearer header. The gateway validates it and enforces RBAC; the MCP server is a stateless proxy that owns no authz. Tokens are tied to your email rather than one organisation, permissions resolve per request against your live role, and every write is audited with a source of mcp.

### Can the MCP server make changes to my cloud accounts?

Only as far as you allow. How much an agent may change is one per-organisation setting, Write access, in Settings then Organisation, with four cumulative levels: Read-only, Metadata only, Reversible changes, and Irreversible changes. An agent can never exceed the permissions of the person whose token it holds, and roles, user management, credentials, cloud-account deletion and bulk actions have no write tool at any level.

### Can I limit what an assistant is able to see?

Yes, through the role of the person who mints the token. A PAT can do exactly what that user can do in the UI, no more and no less, including team-scoped access that narrows visibility to the resources a team owns. Some things are never exposed at any level of write access: get_service_config returns environment variable keys with every value redacted, and no tool reveals an env var value for any role.
