---
title: "MCP Server - Let AI Agents Notify You or Call You"
sidebarTitle: MCP Server
description: "Connect Claude Code, Codex, Cursor, ChatGPT and other AI agents to Echobell's official MCP server so they can send you a push notification or a phone call."
---

# MCP Server for AI Agents

Echobell runs an official [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server. Connect it to your AI agent — Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude, ChatGPT or any other MCP client — and the agent gets one tool, `notify`, that sends a notification through one of your Echobell channels.

Start a long refactor, a test run or a deploy, walk away, and ask the agent to tell you when it's done. Your phone buzzes when the work finishes, shows a time-sensitive alert when the agent needs you, or rings like a phone call when something goes badly wrong.

## How It Works

- It's a **remote** MCP server at `https://mcp.echobell.one/mcp`, using the Streamable HTTP transport. There's nothing to install: no npm package, no `npx`, no local process.
- Each MCP URL belongs to **one channel**. When the agent calls `notify`, everyone subscribed to that channel gets the notification, each at the [notification type](/docs/notification) they chose.
- The credential is the channel's **trigger token** — the same token that ends the channel's webhook URL. The MCP server works like the channel's [webhook](/docs/webhook), with a tool the agent knows how to call.

<Callout type="info">
  Create a dedicated channel for your agents, for example "AI Agents", and
  subscribe to it at **Calling**. Your agents can then pick any level up to a
  call, and you can share the channel with teammates who want the same alerts.
</Callout>

## Get Your MCP URL

### From the App

1. Open the Echobell app and tap the channel you want your agent to use.
2. In the channel details, find the **Connect AI Agent** section.
3. Copy the **MCP Server URL**, or copy the ready-made setup snippet for your agent.

### From the Webhook URL

The MCP URL uses the same token as the channel's webhook URL. Take the token from the end of the webhook URL and put it after `https://mcp.echobell.one/mcp/`:

```
Webhook URL: https://hook.echobell.one/t/<channel-token>
MCP URL:     https://mcp.echobell.one/mcp/<channel-token>
```

<Callout type="warn">
  The MCP URL contains your channel's trigger token. Anyone who has it can send
  notifications to the channel's subscribers, so keep it as private as a
  password. See [Security](#security).
</Callout>

## Set Up Your Agent

Every snippet below uses the URL form. Replace `<channel-token>` with your channel's trigger token, or paste the snippet the app gives you, which already has it filled in.

### Claude Code

```bash
claude mcp add --transport http echobell https://mcp.echobell.one/mcp/<channel-token>
```

Add `--scope user` to make the server available in every project, not only the current one.

### Codex

Add this to `~/.codex/config.toml`:

```toml
[mcp_servers.echobell]
url = "https://mcp.echobell.one/mcp/<channel-token>"
```

### Cursor

Add this to `~/.cursor/mcp.json`, or to `.cursor/mcp.json` in a project:

```json
{
  "mcpServers": {
    "echobell": {
      "url": "https://mcp.echobell.one/mcp/<channel-token>"
    }
  }
}
```

### VS Code (GitHub Copilot)

Add this to `.vscode/mcp.json` in your workspace, then use the tool from Copilot Chat in agent mode:

```json
{
  "servers": {
    "echobell": {
      "type": "http",
      "url": "https://mcp.echobell.one/mcp/<channel-token>"
    }
  }
}
```

If `.vscode/mcp.json` is committed to your repository, use the [header form with an input prompt](#header-form) instead, so the token stays out of the file.

### Windsurf

Add this to `~/.codeium/windsurf/mcp_config.json`:

```json
{
  "mcpServers": {
    "echobell": {
      "serverUrl": "https://mcp.echobell.one/mcp/<channel-token>"
    }
  }
}
```

### Gemini CLI

Add this to `~/.gemini/settings.json`:

```json
{
  "mcpServers": {
    "echobell": {
      "httpUrl": "https://mcp.echobell.one/mcp/<channel-token>"
    }
  }
}
```

### Claude Desktop and claude.ai

1. Open **Settings → Connectors**.
2. Choose **Add custom connector**.
3. Enter the name `Echobell` and the URL `https://mcp.echobell.one/mcp/<channel-token>`, then add it.

The connector is available in Claude on the web and in the desktop app.

### ChatGPT

1. Turn on developer mode in ChatGPT's settings.
2. Open **Settings → Connectors** and choose **Create**.
3. Enter the URL `https://mcp.echobell.one/mcp/<channel-token>` and set authentication to **No authentication** — the token in the URL is the credential.

### Other MCP Clients

Any client that supports the Streamable HTTP transport works. Give it the URL `https://mcp.echobell.one/mcp/<channel-token>`, or use the header form below.

### Header Form

Instead of putting the token in the URL, you can send it in an `Authorization` header. Both forms are equivalent.

```
URL:            https://mcp.echobell.one/mcp
Authorization:  Bearer <channel-token>
```

With Claude Code:

```bash
claude mcp add --transport http echobell https://mcp.echobell.one/mcp \
  --header "Authorization: Bearer <channel-token>"
```

In VS Code, an input prompt keeps the token out of `.vscode/mcp.json`, so the file is safe to commit. VS Code asks for the token the first time the server starts and stores it securely:

```json
{
  "inputs": [
    {
      "type": "promptString",
      "id": "echobell-token",
      "description": "Echobell channel trigger token",
      "password": true
    }
  ],
  "servers": {
    "echobell": {
      "type": "http",
      "url": "https://mcp.echobell.one/mcp",
      "headers": {
        "Authorization": "Bearer ${input:echobell-token}"
      }
    }
  }
}
```

## The `notify` Tool

The server exposes a single tool, `notify`. Your agent decides how to fill it in from your prompt.

| Argument | Type | Required | Description |
|---|---|---|---|
| `title` | string | Yes | Notification title. |
| `body` | string | No | Notification body. |
| `link` | string (URL) | No | A link opened when you tap the notification, such as a pull request, a build log or a dashboard. |
| `urgency` | string | No | `normal`, `time-sensitive` or `calling`. Leave it out to use each subscriber's own level. See [Urgency](#urgency). |

## Urgency

Everyone who subscribes to a channel picks a notification type for it in the app: Normal, Time Sensitive or Calling. That choice is the **highest** level the channel can reach them at.

- When the agent leaves `urgency` out, each subscriber gets the level they chose.
- When the agent sends `urgency`, it can only **lower** a subscriber's level, never raise it. If you subscribed at Calling, `"urgency": "normal"` arrives as a normal notification. If you subscribed at Normal, `"urgency": "calling"` still arrives as a normal notification.

This lets one channel cover everything. Subscribe at Calling, then tell the agent to send routine updates as `normal` and to use `calling` only when something is broken.

Unlike `notificationType` in a webhook request, `urgency` also works on channels with a custom template.

### Calling Requires Echobell Premium

Call notifications are an Echobell Premium feature. When the agent asks for `calling`, a subscriber without Premium gets a **time-sensitive** notification instead — the same thing that happens with the app and webhooks.

### One Call a Minute per Channel

A channel rings each subscriber at most once a minute. If the agent asks for another call within that minute — for example because it is stuck retrying — the subscriber gets a **time-sensitive** notification instead, which still breaks through Focus. Webhook and email triggers follow the same rule.

The agent is told about both fallbacks. The tool result lists every fallback, so the agent knows the phone didn't ring and can say so instead of assuming you were called.

## What the Agent Gets Back

Each `notify` call returns a short text summary for the agent plus structured data:

```json
{
  "notificationTriggered": true,
  "reason": null,
  "requestedUrgency": "calling",
  "recipients": 1,
  "deliveredUrgency": { "normal": 0, "time-sensitive": 1, "calling": 0 },
  "fallbacks": [
    {
      "from": "calling",
      "to": "time-sensitive",
      "reason": "premium-required",
      "recipients": 1
    }
  ]
}
```

| Field | Meaning |
|---|---|
| `notificationTriggered` | `true` when a notification was sent. |
| `reason` | Why nothing was sent: `conditions-not-met` (the channel's [conditions](/docs/conditions) didn't match) or `no-subscribers` (nobody is subscribed to the channel). `null` when a notification was sent. |
| `requestedUrgency` | The `urgency` the agent asked for, or `null` when it left it out. |
| `recipients` | How many subscribers were notified. |
| `deliveredUrgency` | How many subscribers got each level. |
| `fallbacks` | Subscribers who got a lower level than requested, and why: `premium-required` (calling needs Premium), `subscriber-setting` (the subscriber's own level for the channel is lower) or `call-cooldown` (the channel already called that subscriber within the last minute). |

## Passthrough and Template Channels

The MCP server works with both kinds of channel:

- **Passthrough channels** (the default) show the `title` and `body` exactly as the agent sends them.
- **Template channels** (with **Custom Template** turned on under **Advanced Settings**) build the notification from your [templates](/docs/template). `title`, `body`, `link`, `externalLink` and `urgency` are available as template variables, and the channel's [conditions](/docs/conditions) still apply. When the conditions don't match, nothing is sent and the agent gets `reason: "conditions-not-met"`.

## Example Prompts

Once the server is connected, ask for notifications in plain language:

- "Run the full test suite and notify me with Echobell when you're done."
- "Refactor the payment module. Send me a time-sensitive Echobell alert if you need a decision from me."
- "Deploy to staging. Call me if the deploy fails, otherwise send a normal notification with the URL."
- "When the migration finishes, notify me with a summary and a link to the pull request."

To make it a habit, add a line like this to your agent's instructions file (`CLAUDE.md`, `AGENTS.md`, `.cursorrules` and so on):

```
When a task takes longer than a few minutes, call the Echobell notify tool when it finishes.
Use urgency "calling" only when something is broken and needs me right away.
```

## Security

- **The token is the credential.** Whoever has the MCP URL (or the token) can send notifications to the channel's subscribers. It can't read anything or change your account — the only thing it can do is notify.
- **Keep it out of shared files.** Don't commit a config file that contains the URL form. For project-level config, use the [header form](#header-form) with an input prompt or an environment variable.
- **Revoke access by resetting the trigger token.** Open the channel in the app and reset its trigger token. The old MCP URL stops working right away (requests get `401 Unauthorized`), and so does the old webhook URL. Update your agents and webhook callers with the new token.

## Limits and Errors

- **Rate limit**: Each token accepts up to 120 MCP requests a minute. MCP requests have their own budget, separate from the channel's webhook requests.
- **401 Unauthorized**: The token is missing, wrong, or has been reset.

## Related

- [Webhooks](/docs/webhook) — trigger the same channel from scripts, CI and other services
- [Notification types](/docs/notification) — how Normal, Time Sensitive and Calling differ
- [Templates](/docs/template) and [Conditions](/docs/conditions) — shape and filter notifications
