# Developer recipes

> Three recipes for the CLSTR API and MCP server. HTML version: https://clstr.news/developers/recipes

- REST base URL: `https://api.clstr.news/v1`, with `Authorization: Bearer clstr_YOUR_KEY`
- MCP endpoint: `https://mcp.clstr.news/mcp`. Each MCP step below is the `name` and `arguments` of a `tools/call`.
- Full reference: https://clstr.news/developers.md

## 1. Morning brief that only reports what changed

Tier: Any tier, Free included. Works from an assistant connector on a free account.

Based on how one of our users runs a daily brief from an assistant connector. Once a day, pull what moved in the last 24 hours, open the situations that matter, and write only what is new since yesterday.

1. Pull the situations that moved in the last 24 hours. MCP `get_top_situations`:

```json
{"name":"get_top_situations","arguments":{"window":"24h","sort":"relevance","limit":25}}
```

2. Keep the rows with `significance_score` of 7 or higher.

3. For each one, open its timeline, newest first. MCP `get_situation_timeline`:

```json
{"name":"get_situation_timeline","arguments":{"situation_id":"<id>","timeline_limit":10}}
```

4. Dedupe against yesterday's brief: store, per situation `id`, the timeline entry `id`s you already reported. Anything not in that set is new. Use `last_updated` only as a quick skip (unchanged since yesterday), never as the only check: it is the date of the newest event, not the time the situation was last written, so a late-published cluster can join with an older date.

5. Write each new entry as `Update: <title> (<sources> sources) <url>`.

A prompt to start from:

```text
Every morning, call get_top_situations with window "24h" and sort
"relevance". For each situation with significance 7 or higher, call
get_situation_timeline. Compare with yesterday's brief and write only new
developments, each as "Update:" followed by one sentence and the clstr.news
link. If nothing changed, say "No material change" and stop. Cite every link.
```

Limits you will hit and what changes them: on Builder, `summary: "full"` puts each situation's full summary in the list itself, so the brief can quote it without opening every timeline. Calls are not the limit: a brief like this is 1 + N calls a day, and Free allows 100.

## 2. Crisis dashboard poll

Tier: Any tier, Free included. REST with an API key.

A wall display of what is developing. Refresh the fresh set on a schedule, and redraw the week behind it once a day.

1. Hourly: the last day. REST `GET /situations?days=1&sort=relevance&limit=50`:

```bash
curl -s "https://api.clstr.news/v1/situations?days=1&sort=relevance&limit=50" \
  -H "Authorization: Bearer clstr_YOUR_KEY"
```

2. Daily: the week behind it. REST `GET /situations?days=7&sort=relevance&limit=50`:

```bash
curl -s "https://api.clstr.news/v1/situations?days=7&sort=relevance&limit=50" \
  -H "Authorization: Bearer clstr_YOUR_KEY"
```

3. Diff on `id`. Redraw a row when its `cluster_count` or `last_updated` changes.

4. Read `X-Summary-Mode` on every response. It says which summary mode you were served: `preview` or `full`. Ask for `summary=full` on Free and you get the preview list with `X-Summary-Mode: preview`, never an error.

The math, stated plainly: hourly plus one daily call is 25 requests a day, against the 100 Free allows. What is left is room for `GET /situations/{id}` on anything you click into. Polling every 15 minutes is 97 a day. Faster than that mostly returns the same list: situations update as new coverage is clustered.

Limits you will hit and what changes them: capability first. Builder serves `summary=full` in the list (one call instead of 1 + 50), and `days` up to 30 for the backdrop instead of 7. Caps second: 5,000 requests a day instead of 100, for many dashboards on one account.

## 3. Topic monitor for an agent

Tier: Any API key, Free included, or a signed-in connector.

Search a topic on a schedule and only wake the agent when a known situation grows or a new one appears.

1. On a schedule, search the topic. MCP `search_situations`:

```json
{"name":"search_situations","arguments":{"query":"Red Sea shipping","days":7,"limit":15}}
```

2. From each hit's `situation`, keep `id` and `cluster_count`, and skip hits whose `situation` is null (an event not in a situation yet). A search hit names its situation's `id`, `title`, `slug` and `cluster_count`, not its `last_updated`, and `cluster_count` is all this needs.

3. A new situation `id`, or a known one whose `cluster_count` grew: open it and hand the new entries to the agent. Otherwise do nothing. MCP `get_situation_timeline`:

```json
{"name":"get_situation_timeline","arguments":{"situation_id":"<id>","timeline_limit":5}}
```

4. Over REST the same search is one request. Its hits are events without the `situation` block, so key your state on each event `id` instead: an `id` you have not seen is a new cluster, and `GET /clusters/{id}` names the situation it belongs to. REST `GET /search?q=Red%20Sea%20shipping&days=7`:

```bash
curl -s "https://api.clstr.news/v1/search?q=Red%20Sea%20shipping&days=7" \
  -H "Authorization: Bearer clstr_YOUR_KEY"
```

Limits you will hit and what changes them: search is the limit a free key reaches first. Free has 10 searches a day and each page of results is one search, so one topic every 3 hours, or 10 topics once a day. Builder searches 30 days back instead of 7, and has 250 searches a day: 10 topics every hour.

---
Caps and plans: https://clstr.news/developers#limits. Questions? https://clstr.news/contact
