---
title: MCP server
description: Connect AI assistants (Claude, Cursor, VS Code and others) to your installation's API through the built-in MCP endpoint at /mcp — authentication, client configuration, tools and safety rules.
url: https://nexcmp.com/docs/developers/mcp/
applies_to: NexCMP 1.6.1
updated: 2026-11-02
---

# MCP server

> **Where in the portal:** API reference › Tools (`https://<your-domain>/apidoc`) shows the endpoint and client snippets; keys are created at API keys (`/api-keys`). There is no setting in the admin: the endpoint is part of the panel.

## What it does

The **Model Context Protocol (MCP)** lets an AI assistant call tools. NexCMP serves an MCP endpoint at `https://<your-domain>/mcp`. Every public API operation becomes one **tool** (`vm_list`, `vm_start`, `billing_wallet`, ...), so a customer can ask their assistant "which of my VMs are running?" or "stop the staging VM". The assistant acts with the customer's own API key and permissions only.

::: tip Configuring NexCMP itself with AI?
This page is the **customer** MCP endpoint (`/mcp`). To let an AI assistant configure your own panel as an administrator, see [Configure with AI](https://nexcmp.com/docs/configure-with-ai/mcp-admin/) (endpoint `/mcp/admin`, admin keys `ak_`).
:::

## Requirements

| Item | Requirement |
|---|---|
| Server | Nothing to install: the endpoint is served by the panel and reachable wherever the panel is. Your reverse proxy must forward `/mcp` to the panel. |
| Customer | An [API key](https://nexcmp.com/docs/developers/api-keys/) (`vk_...`) with the scopes the assistant needs. |
| Client | An MCP client that supports the **Streamable HTTP** transport and a custom `Authorization` header: Claude Code, Claude Desktop (through the `mcp-remote` bridge), Cursor, VS Code with Copilot agent mode and similar. |
| Protocol versions | 2025-11-25, 2025-06-18 and 2025-03-26. |

## Prepare the infrastructure

Nothing, beyond making sure `https://<your-domain>/mcp` is not blocked by a firewall or a proxy rule. A browser-based MCP client from another origin is refused unless that origin is allowed; command-line and desktop clients send no `Origin` header and work as they are.

## Connect (customer side)

1. Create an API key in the portal (**API keys › Create key**) with only the scopes you want the assistant to use, a short expiry and, if possible, an IP restriction.
2. Add the server to your client. Replace `cloud.example.com` and the key.

   **Claude Code**

   ```bash
   claude mcp add --transport http cloud https://cloud.example.com/mcp \
     --header "Authorization: Bearer vk_XXXX"
   ```

   **Cursor** (`~/.cursor/mcp.json` or `.cursor/mcp.json`; set `CLOUD_API_KEY` in the environment Cursor starts from):

   ```json
   {
     "mcpServers": {
       "cloud": {
         "url": "https://cloud.example.com/mcp",
         "headers": { "Authorization": "Bearer ${env:CLOUD_API_KEY}" }
       }
     }
   }
   ```

   **Claude Desktop** (needs Node.js 18+; `claude_desktop_config.json`), through the `mcp-remote` bridge:

   ```json
   {
     "mcpServers": {
       "cloud": {
         "command": "npx",
         "args": ["-y", "mcp-remote", "https://cloud.example.com/mcp", "--header", "Authorization:${CLOUD_AUTH_HEADER}"],
         "env": { "CLOUD_AUTH_HEADER": "Bearer vk_XXXX" }
       }
     }
   }
   ```

   Write the header without a space after the colon and put the whole value in the environment variable, as above.

3. Restart the client and ask it to list your tools.


Check the connection without a client:

```bash
curl -s https://cloud.example.com/mcp \
  -H "Authorization: Bearer vk_XXXX" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

## How it works

| Item | Detail |
|---|---|
| Endpoint | `POST /mcp` with a JSON-RPC 2.0 message; the answer is `application/json`. `GET /mcp` answers 405 (no server-to-client stream); `DELETE /mcp` ends the session. |
| Authentication | Only `Authorization: Bearer vk_...` (session tokens, cookies and admin keys are refused with 401 and a `WWW-Authenticate: Bearer` header). |
| Session | `Mcp-Session-Id` is issued by `initialize`, bound to that key, valid 24 hours; at most 16 sessions per key. |
| Tools | One per public API operation visible to the key. The tool name is the CLI command with `_` instead of spaces and dashes (`vm firewall add` becomes `vm_firewall_add`) and equals the OpenAPI `operationId`. A tool is listed only when the key has its scope and the module is enabled. |
| Capabilities | Tools only (no resources or prompts). |
| Size | Request body up to 1 MB; tool result text up to about 100 KB (the rest is cut with a note); a call takes at most 55 seconds. |

### Safety rules

- **Same gate as REST.** Each `tools/call` goes through the panel's own request pipeline: scope, site, IP restriction, rate limit, idempotency, ownership checks (404 for other people's resources) and quotas all apply. MCP cannot grant anything the key does not have.
- **Confirmation.** Tools that cost money, delete, or return credentials (console tickets, kubeconfig, S3 or SSH secrets, password resets, new keys) require the argument `confirm: true`. The tool description tells the assistant to pass it only after the user has approved, so an instruction hidden in a web page or log cannot trigger it on its own.
- **Idempotency.** Paid tools accept `idempotency_key`; if omitted a stable key is derived from the tool name and arguments, so an identical retry cannot charge twice.
- **Not exposed as tools:** streaming endpoints (the AI Agent chat), one-time SSH or console WebSocket tickets, binary downloads, and the VPN app endpoints (`/v1/ext/*`).
- **Never possible:** the API never allows top-ups, password changes, deleting the account or creating keys, so no assistant can do them.

### Limits

| Limit | Default |
|---|---|
| Tool calls per key | 60 per minute |
| MCP requests per key | 240 per minute |
| Plus the normal key and account limits | See [REST API](https://nexcmp.com/docs/developers/api/#rate-limits) |

Over the limit the endpoint answers HTTP 429 with a JSON-RPC error and `Retry-After`.

## Verify

1. The `curl` command above returns a JSON-RPC result with a `tools` list. Only tools matching the key's scopes appear.
2. In your client ask "list my VMs": the assistant calls `vm_list` and shows the result.
3. In the portal the key's **Last used** time moves, and write calls appear in the **Key usage log**.

## Limits & notes

- **Browser sign-in (OAuth).** The reference page also describes signing in through the browser for clients that support MCP OAuth. In an installed NexCMP the supported, tested method is the API key (or `cmp login` for the CLI).
- **Reseller sites** do not show the MCP section; their customers use the reseller's domain for the API.
- **Least privilege.** Create a dedicated key per assistant with read scopes first; add write scopes only when needed.
- Revoke the key in **API keys** to cut the assistant's access at once.

## Troubleshooting

| Symptom | Cause | Fix |
|---|---|---|
| 401 with `WWW-Authenticate: Bearer` | No key, wrong key, or a session token | Send `Authorization: Bearer vk_...`. |
| 403 about `Origin` | A browser page on another origin | Use a desktop or CLI client; or ask your administrator to allow the origin (`mcp_allowed_origins`). |
| 404 on a request with `Mcp-Session-Id` | Session belongs to another key or expired | Run `initialize` again. |
| 405 on `GET /mcp` | Expected: the server has no event stream | Use POST only (clients do this automatically). |
| The tool list is short | Key scopes or modules | Add scopes to the key; enable the module. |
| Tool answers it needs `confirm: true` | Paid, delete or sensitive tool | The assistant must set `confirm` after you approve. |
| 429 | MCP or key rate limit | Wait for `Retry-After`. |
| Client cannot connect with a header | Client without custom-header support | Use the `mcp-remote` bridge. |


