# MCP server

The Model Context Protocol (MCP) lets an AI assistant call tools on your behalf. EarlyWave's MCP server gives Claude, Cursor, VS Code and other MCP clients the same 18 read-only operations as the REST API: trends across every source, coverage by country, your monitors, feeds, folders, articles and saved items.

| Setting | Value |
|---|---|
| Address | `https://api.earlywave.ai/mcp` |
| Transport | Streamable HTTP, stateless, `POST` only |
| Authentication | `Authorization: Bearer <key>`, a key with the `mcp` scope |
| Server name | `earlywave` |
| Limit | 60 tool calls per minute and 10,000 a month on Pro (300 and 50,000 on Max), shared with the REST API |

Create a key with the `mcp` scope in EarlyWave › **Settings › API & MCP** ([open it](https://www.earlywave.ai/settings/developers)). In the snippets below, replace `YOUR_KEY` with it.

## Client setup

### Claude Code

```bash
claude mcp add --transport http earlywave https://api.earlywave.ai/mcp \
  --header "Authorization: Bearer YOUR_KEY"
```

Check it with `claude mcp list`. Add `--scope user` to use it in every project.

### Cursor

In `.cursor/mcp.json` (this project) or `~/.cursor/mcp.json` (every project):

```json
{
  "mcpServers": {
    "earlywave": {
      "url": "https://api.earlywave.ai/mcp",
      "headers": { "Authorization": "Bearer YOUR_KEY" }
    }
  }
}
```

### VS Code

In `.vscode/mcp.json`:

```json
{
  "servers": {
    "earlywave": {
      "type": "http",
      "url": "https://api.earlywave.ai/mcp",
      "headers": { "Authorization": "Bearer YOUR_KEY" }
    }
  }
}
```

The tools appear in Copilot Chat in agent mode.

### Claude Desktop

Claude Desktop starts local servers, so it reaches EarlyWave through the `mcp-remote` bridge (Node.js required). In `claude_desktop_config.json` (Settings › Developer › Edit Config):

```json
{
  "mcpServers": {
    "earlywave": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://api.earlywave.ai/mcp",
        "--header",
        "Authorization: Bearer ${EARLYWAVE_API_KEY}"
      ],
      "env": { "EARLYWAVE_API_KEY": "YOUR_KEY" }
    }
  }
}
```

Restart Claude Desktop after saving.

### Windsurf and other clients

Any client that speaks Streamable HTTP needs two things: the address `https://api.earlywave.ai/mcp` and the header `Authorization: Bearer YOUR_KEY`. A client that only starts local servers can use the `mcp-remote` bridge shown for Claude Desktop.

## Tools

Each tool is one operation of the [REST API](https://www.earlywave.ai/developers/reference), with the same arguments and the same JSON answer, returned as text.

| Tool | What it returns | Arguments | REST twin |
|---|---|---|---|
| `list_trends` | List trends. Stories EarlyWave detects across every source it reads, strongest signal first. Filter by category, stage, the country a story is about, the country of its publishers, reach, or how recently it started. | `query`, `category`, `stage`, `country`, `publisher_country`, `reach`, `since_hours`, `sort`, `limit`, `offset` | `GET /trends` |
| `get_trend` | Get a trend. A trend with its summary, countries, languages, entities, keywords and its 10 latest articles. | `trend_id` (required) | `GET /trends/{trend_id}` |
| `get_trend_articles` | List a trend's articles. Every article of a trend with its source (title, site, country), newest or oldest first. | `trend_id` (required), `sort`, `limit`, `offset` | `GET /trends/{trend_id}/articles` |
| `get_trend_coverage` | Get where a trend is covered. Publisher countries and languages of a trend (sources = distinct sites) and its last 7 days hour by hour. | `trend_id` (required) | `GET /trends/{trend_id}/coverage` |
| `list_monitors` | List your monitors. Your monitors (archived ones excluded), with their counts and next check. | — | `GET /monitors` |
| `get_monitor_results` | Get a monitor's results. What a monitor found over the last days (newest first), with its sources and the current answers to its questions. | `monitor_id` (required), `days`, `query`, `limit` | `GET /monitors/{monitor_id}/results` |
| `find_feeds` | List your subscribed feeds. Lists the RSS feeds the account is subscribed to, optionally filtered by a keyword (title, description, address) or a domain. | `query`, `domain`, `limit`, `offset` | `GET /feeds` |
| `discover_feeds` | Search the feed catalogue. Searches every feed EarlyWave reads (not only your subscriptions), most-followed first. | `query` (required), `language`, `country`, `limit`, `offset` | `GET /feeds/discover` |
| `get_feed` | Get one of your feeds. Details of a feed you are subscribed to, with its 24-hour and 7-day article counts. | `feed_id` (required) | `GET /feeds/{feed_id}` |
| `get_feed_items` | List a feed's articles. Articles of one of your feeds, newest first. | `feed_id` (required), `limit`, `offset` | `GET /feeds/{feed_id}/items` |
| `list_categories` | List your folders. Your feed folders, with the number of feeds in each. | — | `GET /categories` |
| `get_category_items` | List a folder's articles. Articles from the feeds of one of your folders, newest first. | `category_id` (required), `limit`, `offset` | `GET /categories/{category_id}/items` |
| `get_all_items` | List all your articles. Articles from all your feeds, newest first. | `limit`, `offset` | `GET /items` |
| `search_articles` | Search your articles. Articles of your feeds whose title, description, summary or keywords contain the query, newest first. | `query` (required), `limit`, `offset` | `GET /articles/search` |
| `get_article` | Get an article. One article from your feeds, with its text (up to 10,000 characters), summary and keywords. | `article_id` (required) | `GET /articles/{article_id}` |
| `list_saved` | List your saved items. Articles, pages and searches you saved, newest first. | `type`, `limit`, `offset` | `GET /saved` |
| `discover_items` | Search all recent articles. Recent articles from every source EarlyWave reads (not only your feeds), by keywords or latest first. | `query`, `language`, `hours_back`, `limit`, `offset` | `GET /discover` |
| `discover_top_keywords` | Top keywords. The most frequent keywords, entities, themes or places in recent articles. | `type`, `hours_back`, `limit` | `GET /discover/keywords` |

Lists take `limit` (up to 100) and `offset`, and answer `has_more`. Countries are ISO alpha-2 codes (`FR`). Answers longer than 50,000 characters are cut; ask for a smaller `limit`.

## Example prompts

- *"What are the breakout stories in tech since yesterday?"* → `list_trends` with `category=tech`, `stage=breakout`, `since_hours=24`.
- *"Which stories about France are covered abroad?"* → `list_trends` with `country=FR` and `reach=international,global`.
- *"Who reported the rail strike first, and from which country?"* → `get_trend_articles` with `sort=oldest`.
- *"In which countries and languages is this story covered, and when did it peak?"* → `get_trend_coverage`.
- *"Summarise what my monitors found this week, with sources."* → `list_monitors`, then `get_monitor_results` with `days=7`.
- *"Find French feeds about climate I don't follow yet."* → `discover_feeds` with `query=climate`, `country=FR`.
- *"What did I save this week?"* → `list_saved`.

The server also sends the assistant a short guide to its tools, so plain questions work: you rarely need to name a tool.

## Test it without a client

The server is stateless: each `POST` stands alone, with no session to open first. List the tools with curl:

```bash
curl https://api.earlywave.ai/mcp \
  -H "Authorization: Bearer $EARLYWAVE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

Call one:

```bash
curl https://api.earlywave.ai/mcp \
  -H "Authorization: Bearer $EARLYWAVE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"list_trends","arguments":{"country":"FR","limit":3}}}'
```

The tool's JSON answer is in `result.content[0].text`.

## Troubleshooting

| Symptom | Cause |
|---|---|
| `401` | Missing or unknown key, or a key without the `mcp` scope. |
| `403` | The account's plan does not include MCP, or the account is inactive. |
| `405` on `GET` or `DELETE` | The server is stateless: it only answers `POST`. Use the Streamable HTTP transport, not SSE. |
| `406` | The request must accept both `application/json` and `text/event-stream`. Clients do this for you. |
| Tool error "Rate limit exceeded" | 60 calls per minute per account on Pro (300 on Max), REST included. Wait for the next minute. |
| Tool error "Monthly quota exceeded" | 10,000 calls a month on Pro (50,000 on Max), REST included. It resets on the 1st; Max raises it. |
| Tool error naming a parameter | A wrong argument, for example a three-letter country code. The message says which. |
| No tools listed | Restart the client after editing its configuration, and check the key has the `mcp` scope. |

---
Source: https://www.earlywave.ai/developers/docs/mcp · All docs: https://www.earlywave.ai/llms.txt
