> ## Agent Instructions
>
> Base URL: https://api.anysite.io
> Authentication: send the `access-token` header. Do NOT use `Authorization: Bearer`.
> Full endpoint catalog: https://app.anysite.io/docs
# Data Analysis (query_cache)

Server-side data filtering, aggregation, and export without consuming context window tokens

## Server-Side Data Analysis

> 
`query_cache` is one of the most powerful features of the MCP Server — it allows you to **analyze data without consuming context window tokens**.

### The Problem

When you search for 50 LinkedIn profiles, all 50 results are returned into the LLM's context. Filtering, sorting, or aggregating requires the LLM to process all data in-context — expensive and limited by context size.

### The Solution: ClickHouse-Backed Cache

Every `execute()` call stores results in a ClickHouse cache (TTL: 7 days). The `query_cache` tool lets you query this cache server-side — only the filtered/aggregated results are returned to context.

```text
execute("linkedin", "search", "search_users", {keywords: "CTO", count: 100})
  → Returns first 10 items + cache_key
  → All 100 results stored in ClickHouse cache

query_cache(cache_key, conditions=[{field: "followers", op: ">", value: 5000}])
  → Returns only matching profiles (server-side filtering)
  → Context receives only the filtered subset, not all 100
```

---

## Filtering

Use `conditions` to filter cached results by any field:

```json
query_cache(cache_key, conditions=[
  {"field": "location", "op": "contains", "value": "San Francisco"},
  {"field": "followers", "op": ">", "value": 500}
])
```

Multiple conditions are combined with AND logic.

### Supported Filter Operators

| Operator | Description | Example |
|----------|-------------|---------|
| `=` | Exact match | `{"field": "country", "op": "=", "value": "US"}` |
| `!=` | Not equal | `{"field": "status", "op": "!=", "value": "inactive"}` |
| `>` | Greater than | `{"field": "followers", "op": ">", "value": 1000}` |
| `<` | Less than | `{"field": "age", "op": "<", "value": 30}` |
| `>=` | Greater or equal | `{"field": "score", "op": ">=", "value": 4.5}` |
| `<=` | Less or equal | `{"field": "price", "op": "<=", "value": 100}` |
| `contains` | Substring match | `{"field": "title", "op": "contains", "value": "Engineer"}` |
| `not_contains` | Substring exclusion | `{"field": "bio", "op": "not_contains", "value": "retired"}` |

---

## Aggregation

Calculate summary statistics without loading individual records:

```json
query_cache(cache_key, aggregate={"field": "followers", "op": "avg"})
```

### Supported Aggregation Functions

| Function | Description | Example |
|----------|-------------|---------|
| `count` | Count records | `{"op": "count"}` (field optional) |
| `sum` | Sum values | `{"field": "likes", "op": "sum"}` |
| `avg` | Average value | `{"field": "followers", "op": "avg"}` |
| `min` | Minimum value | `{"field": "price", "op": "min"}` |
| `max` | Maximum value | `{"field": "score", "op": "max"}` |
| `uniq` | Count unique values | `{"field": "country", "op": "uniq"}` |

---

## Group By

Combine aggregation with grouping to get breakdowns:

```json
query_cache(cache_key, aggregate={"field": "followers", "op": "count"}, group_by="industry")
```

**Result:**
```json
{
  "aggregate": {
    "groups": {
      "Technology": 45,
      "Finance": 23,
      "Healthcare": 12
    },
    "op": "count"
  },
  "cache_key": "abc123..."
}
```

---

## Sorting

Sort cached results by any field:

```json
query_cache(cache_key, sort_by="followers", sort_order="desc", limit=10)
```

Returns only the top 10 results — the rest stay in cache, not in context.

---

## Combined Example

A full workflow combining all features:

```text
1. execute("linkedin", "search", "search_users", {keywords: "VP Engineering", count: 200})
   → 200 profiles cached, first 10 returned + cache_key

2. query_cache(cache_key, conditions=[
     {field: "location", op: "contains", value: "Bay Area"},
     {field: "followers", op: ">", value: 500}
   ])
   → Filter to Bay Area VPs with 500+ followers

3. query_cache(cache_key,
     aggregate={field: "followers", op: "avg"},
     group_by="company")
   → Average follower count by company (across all 200 profiles, not just the Bay Area subset)

4. query_cache(cache_key,
     sort_by="followers", sort_order="desc", limit=5)
   → Top 5 most-followed VPs (from all 200 profiles)

5. export_data(cache_key, "csv")
   → Download all 200 profiles as CSV file
```

> 
**Key benefit**: Step 1 makes a single API call to collect data. Steps 2-5 are cache operations at zero additional API cost — they don't load all 200 profiles into context. Only the filtered/aggregated results are returned to the LLM.

---

## Export Data

Download full cached datasets as files:

```json
export_data(cache_key, "csv")
```

> 
`export_data` always exports the **full dataset** stored under the `cache_key`, regardless of any filters applied via `query_cache`. Filters only affect what is returned to context — they do not modify the cached data.

### Supported Formats

| Format | Description |
|--------|-------------|
| `json` | JSON array |
| `csv` | Comma-separated values |
| `jsonl` | JSON Lines (one record per line) |

Returns a download URL. Data stays cached for 7 days.

---

## Best Practices

  
#### Use Large Counts

    Fetch more data with `execute()` (count: 100-200), then filter with `query_cache`. Cheaper than multiple small requests.
  

  
#### Filter Before Reading

    Always use `query_cache` to narrow results before loading them into context. Saves tokens and improves response quality.
  

  
#### Aggregate Server-Side

    Use aggregation functions instead of asking the LLM to calculate averages, counts, or sums from raw data.
  

  
#### Export for External Use

    Use `export_data` when you need the full dataset outside of the AI conversation (spreadsheets, databases, reports).
