# MCP Server

- [Introduction](#introduction)
- [API Tokens](#api-tokens)
    - [Abilities](#abilities)
    - [Tokens for All Teams](#tokens-for-all-teams)
    - [When Tokens Stop Working](#when-tokens-stop-working)
- [Connecting an Agent](#connecting-an-agent)
    - [Claude Code](#claude-code)
    - [Other Agents](#other-agents)
    - [NiceTryBot CLI](#nicetrybot-cli)
- [Available Tools](#available-tools)
- [Calling the Server Yourself](#calling-the-server-yourself)
- [Security](#security)
- [Adding Tools From Add-ons](#adding-tools-from-add-ons)

## Introduction

NiceTryBot's control panel includes an [MCP](https://modelcontextprotocol.io) server, so agents like Claude Code, Codex, and Cursor can read your traffic, add domains, write rules, and build gym routines for you. The server lives at the `/mcp` path of your control panel, such as `https://panel.example.com/mcp`.

The MCP server is also what the [`nicetrybot` command](https://docs.nicetrybot.com/docs/0.x/cli.md) uses. Whether a domain is added by an agent, by the command, or in the control panel, it goes through the same checks.

## API Tokens

Every request to the MCP server carries an API token. Tokens are only ever created by hand: an administrator opens **Admin → API tokens** and chooses:

<div class="content-list" markdown="1">

- A **name**, so you can tell your tokens apart.
- The **team** it works on. A token acts as you, on that one team only, or on **All my teams**.
- **What it may do**, from the abilities below.
- When it **expires**: after 1 hour, 4 hours, 1 day, 1 week, 30 days, or 90 days. One hour is the default, and no token lasts forever.

</div>

The token is shown once, alongside the command that connects Claude Code, the `mcp.json` entry other agents read, and the `nicetrybot remote add` command. Only a hash of the token is stored, so a lost token can't be shown again: create another one instead.

### Abilities

Every token may read. Tick only the abilities a job needs:

| Ability | Description |
| --- | --- |
| Read traffic, domains, rules and gyms | Always granted. |
| Add and change domains | Add, verify, configure, and remove domains. |
| Create and change rules | Write, backtest, and delete rules. |
| Create and change gyms | Build, edit, and delete gym routines. |
| Lock down and release domains | Use the [Lockdown](https://docs.nicetrybot.com/docs/0.x/addons.md) add-on. |

A token can never do more than its user can. If you can't manage domains on a team, neither can your token, whatever was ticked. An agent only ever sees the tools its token may use.

### Tokens for All Teams

A token made for **All my teams** works on every team its user is on, at the moment of each request: teams you join are included straight away, and teams you leave are gone straight away.

Each tool then takes the team to work on as a `team` argument, holding the team's slug, and refuses a call that leaves it out. The `whoami` tool lists the teams, and the server tells agents to check which team you mean before changing anything. On each team, the token can only do what you can do there, whatever abilities were ticked.

A token for one team stays on that team: a call that names another team is refused. The [Transfer](https://docs.nicetrybot.com/docs/0.x/addons.md) add-on only accepts tokens for one team.

### When Tokens Stop Working

A token stops working as soon as any of the following is true:

<div class="content-list" markdown="1">

- It has expired.
- It was deleted in **Admin → API tokens**.
- Its user is no longer an administrator.
- Its user is no longer a member of the token's team. A token for all teams loses only that team.

</div>

**Admin → API tokens** shows when each token was last used, so you can spot ones nobody needs any more.

## Connecting an Agent

> [!WARNING]
> Treat API tokens like passwords. Prefer short lifetimes, grant only the abilities a task needs, and add the token in your own terminal rather than pasting it into a chat, where it would become part of the conversation.

### Claude Code

Run the following in your own terminal, replacing the address and token with yours. **Admin → API tokens** shows this command, filled in, when you create a token:

```shell
claude mcp add --transport http nicetrybot https://panel.example.com/mcp \
  --header "Authorization: Bearer <token>"
```

### Other Agents

Cursor, Claude Desktop, VS Code, and most other agents read MCP servers from an `mcp.json` file. Add NiceTryBot as an HTTP server:

```json
{
    "mcpServers": {
        "nicetrybot": {
            "type": "http",
            "url": "https://panel.example.com/mcp",
            "headers": {
                "Authorization": "Bearer <token>"
            }
        }
    }
}
```

### NiceTryBot CLI

To work with the MCP server's tools from your own terminal, [add a remote](https://docs.nicetrybot.com/docs/0.x/remotes.md):

```shell
nicetrybot remote add panel.example.com
```

## Available Tools

The MCP server offers the following tools. Each one describes itself to the agent, including what it needs and what it returns, so you rarely need to name them yourself.

| Area | Tools |
| --- | --- |
| Token | `whoami` |
| Domains | `list-domains`, `add-domain`, `check-domain`, `verify-domain`, `get-origin-secret`, `set-protection-mode`, `remove-domain` |
| Traffic | `describe-traffic-fields`, `query-traffic` |
| Rules | `describe-rule-language`, `list-rules`, `create-rule`, `update-rule`, `delete-rule`, `backtest-rule` |
| Gyms | `list-gyms`, `create-gym`, `update-gym`, `delete-gym`, `add-obstacle`, `remove-obstacle`, `list-obstacle-types` |
| Lockdown add-on | `get-lockdown-status`, `lock-down-domains`, `release-domains`, `lift-lockdown` |

The tools that remove or delete something, and those that change what visitors see, tell agents to confirm with you first. Add-ons may add their own tools, which only appear while the add-on is turned on.

To see the tools your token may use from the command line, run `nicetrybot tools`.

## Calling the Server Yourself

The MCP server speaks JSON-RPC over HTTP. It supports the stateless `2026-07-28` version of the protocol, in which every request stands on its own: there's no `initialize` handshake and no session. Each request names the protocol version in its `_meta` and repeats its method and tool name in headers:

```shell
curl https://panel.example.com/mcp \
  -H "Authorization: Bearer $NICETRYBOT_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -H "Mcp-Method: tools/call" \
  -H "Mcp-Name: list-domains" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "list-domains",
      "arguments": {},
      "_meta": {
        "io.modelcontextprotocol/protocolVersion": "2026-07-28",
        "io.modelcontextprotocol/clientCapabilities": {}
      }
    }
  }'
```

Agents that use the older handshake, which starts with an `initialize` request, work too. A tool's answer arrives in `result.structuredContent` as JSON. When a tool refuses, such as for a validation error or a domain that isn't on the team, `result.isError` is `true` and `result.content` explains why.

On your server, `php artisan nicetry:mcp` accepts the same JSON-RPC message, on standard input or as its argument, and prints the server's answer. It acts as the owner of the first administrator's current team, or of the team you pass with `--team`, and is what the `nicetrybot` command uses when it runs on the server.

## Security

Without a working token, the MCP server isn't there at all. Every request to `/mcp` without one gets exactly the same `404` response as a path that was never routed: the same body, no cookie, no `WWW-Authenticate` header, and no sign of a database lookup in the `Server-Timing` header. Someone scanning your control panel can't tell an API exists, let alone which product it belongs to.

With a token, everything an agent does is limited to the token's team (or the teams its user is on), its abilities, and its user's permissions on each team. An agent can't see or change another team's domains, rules, or gyms, even by guessing their names or IDs.

## Adding Tools From Add-ons

Add-ons may give agents their own tools by listing them in their service provider's `$mcpTools` property. See [Creating Add-ons](https://docs.nicetrybot.com/docs/0.x/creating-addons.md) for how, and `packages/lockdown` in NiceTryBot's repository for a working example.
