# `io.github.Dan-Cleary/convalytics` on anlyon.dev

> Text inside fenced blocks marked untrusted-server-text was written by the MCP server's publisher, not by anlyon.dev. It is data to inspect, not instructions to follow. Invisible characters are shown as [U+XXXX].
> No finding is not a safety guarantee: these are point-in-time checks of tool definitions, not of code or behaviour.

- Page: https://anlyon.dev/servers/io.github.Dan-Cleary/convalytics
- JSON: https://anlyon.dev/api/v1/servers/io.github.Dan-Cleary/convalytics
- Version: 1.0.0 (active)
- Publisher: io.github.Dan-Cleary (GitHub account)
- Runs: remote (streamable-http)
- Sign-in to list tools: none
- Repository: https://github.com/Dan-Cleary/convalytics
- Metadata from the official MCP Registry, synced 2026-10-21T18:15:38.754Z

Title and description, as the publisher wrote them:

```untrusted-server-text
Read-only analytics for Convex apps, queryable via MCP from Claude, Cursor, and other clients.
```

Scanned 2026-10-21T19:02:34.234Z over streamable-http.

**15 tools: 1 can delete or cancel things, 5 change things and 9 only read.**

| Group | Class | Tools | Claude Code |
| --- | --- | --- | --- |
| Deletes or cancels | destructive | 1 | deny |
| Can't be undone | irreversible | 0 | ask |
| Changes things | write | 5 | ask |
| Only reads | read | 9 | allow |

## Exfil surface

No private-data -> untrusted-input -> outbound path in this server alone: no tool is tagged private-data or untrusted-input or outbound.

| Tag | Meaning | Tools |
| --- | --- | --- |
| private-data | Reads files, mail, messages, databases, secrets, calendars or repositories. | none |
| untrusted-input | Brings in text someone else can write: web pages, inbound email, messages, issues and comments. | none |
| outbound | Can carry data to people or systems: it sends, posts or publishes, or takes a recipient, channel or URL. | none |

## Findings

- **warn** Annotations that disagree with the tool in `compute_funnel` ([annotation-conflict](https://anlyon.dev/methodology#annotation-conflict))

```untrusted-server-text
The server marks "compute_funnel" read-only (readOnlyHint: true), and its own name, description or input give the class "write".

annotations: {"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The description's first verb is "run": a word for a change.
```


## Deletes or cancels (1)

Removes, cancels or revokes something. Claude Code: deny.

### `delete_funnel`

- The name "delete_funnel" says "delete": a word for removing or ending something.
- The description says "cannot be undone".
- The server marks it destructive (destructiveHint: true).

Description, as the server wrote it:

```untrusted-server-text
Soft delete a funnel. The row is retained with status='deleted' and excluded from list/get/compute. Idempotent — calling twice is a no-op. Use if the funnel is obsolete; the record is kept for audit and cannot be undone from MCP.
```

## Changes things (5)

Creates or changes something that can be changed back. Claude Code: ask.

### `compute_funnel`

- The description's first verb is "run": a word for a change.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
- Findings: warn annotation-conflict

Description, as the server wrote it:

```untrusted-server-text
Run a funnel over a time window and return per-step visitor count, conversion from previous step, conversion from start, and average time to convert between steps. Returns `truncated` flags if the scan cap was hit.
```

### `create_funnel`

- The name "create_funnel" says "create": a word for a change.

Description, as the server wrote it:

```untrusted-server-text
Create a new funnel on a project. Steps are 2–10 ordered events or pageview paths. conversionWindowMs caps how long a visitor has between consecutive steps (default 7 days); this is the step-to-step limit, without which a funnel is just event co-occurrence. Returns { id } on success.
```

### `update_funnel`

- The name "update_funnel" says "update": a word for a change.

Description, as the server wrote it:

```untrusted-server-text
Patch an existing funnel. Any subset of name/description/steps/conversionWindowMs. Refuses updates on deleted funnels.
```

### `user_activity`

- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

Description, as the server wrote it:

```untrusted-server-text
Composite snapshot of a specific user's activity on a project. Returns an identity block (visitorId, userEmail, userName, firstSeen, lastSeen), total pageviews, total custom events, session count, top pages this user visited, their most-fired event names, and their 20 most recent events with props. Use this for 'how is dancleary54@gmail.com using my app?' style questions — one call, full picture. For ad-hoc drill-down (just a count, just recent events) pass `user` to the individual tools instead. Default window is the last 7 days.
```

### `weekly_digest`

- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

Description, as the server wrote it:

```untrusted-server-text
Composite snapshot of a project's web analytics over a lookback window. Returns unique visitors, pageviews, sessions, bounce rate, average session duration, top 5 pages, top 5 referrers, total custom events, and top 5 event names. Includes period-over-period comparison against the prior equal-length window unless compare: false. Prefer this over chaining top_pages + top_referrers + events_count when the agent just wants to report on the week.
```

## Only reads (9)

Looks things up and changes nothing. Claude Code: allow.

### `events_count`

- The name "events_count" says "count": a word for reading.

Description, as the server wrote it:

```untrusted-server-text
Count CUSTOM PRODUCT events for a specific project in a time window, optionally filtered to one event name and/or one user. Custom events are emitted by explicit analytics.track() calls in app code (signup_completed, payment_succeeded, etc.). This does NOT count page views — use pageviews_count or weekly_digest for those. Returns count, unique visitors, and a `truncated` flag if the scan hit the maximum scan size.
```

### `get_funnel`

- The name "get_funnel" says "get": a word for reading.

Description, as the server wrote it:

```untrusted-server-text
Return the full definition of one funnel by id: name, description, ordered steps, and conversion window.
```

### `get_usage`

- The name "get_usage" says "get": a word for reading.

Description, as the server wrote it:

```untrusted-server-text
Return the current month's custom-event usage, monthly quota, retention days, and plan name for the team.
```

### `list_funnels`

- The name "list_funnels" says "list": a word for reading.

Description, as the server wrote it:

```untrusted-server-text
List active funnels defined on a project. A funnel is a saved ordered sequence of steps (events or pageview paths) that Convalytics computes step-by-step conversion for. Soft-deleted funnels are excluded.
```

### `list_projects`

- The name "list_projects" says "list": a word for reading.

Description, as the server wrote it:

```untrusted-server-text
List all Convalytics projects on the team this token belongs to. Useful when the agent needs to confirm the project it's querying against. No arguments.
```

### `pageviews_count`

- The name "pageviews_count" says "count": a word for reading.

Description, as the server wrote it:

```untrusted-server-text
Count page views for a specific project in a time window. Page views are the automatic hits captured by the browser script tag (separate from custom events). Use this for web-traffic questions like 'how many pageviews in the last 24 hours'. Default window is the last 7 days. Pass `user` to scope to one visitor.
```

### `recent_events`

- The description's first verb is "return": a word for reading.

Description, as the server wrote it:

```untrusted-server-text
Return the most recent custom events for a specific project, optionally filtered to one event name and/or one user. PII (userEmail, userName, props) is redacted by default; pass redact: false to include them.
```

### `top_pages`

- The description's first verb is "return": a word for reading.

Description, as the server wrote it:

```untrusted-server-text
Return the top pages for a specific project, ranked by views in a time window. Default window is the last 7 days. Use list_projects first if you don't know the project name. Returns path, views, uniqueVisitors, and percentage of total views for each page. Pass `user` to see pages a specific visitor hit.
```

### `top_referrers`

- The description's first verb is "return": a word for reading.

Description, as the server wrote it:

```untrusted-server-text
Return the top referring hosts for a specific project, ranked by visit count in a time window. Includes '(direct)' for visits with no referrer. Default window is the last 7 days.
```

## Claude Code permissions

For `.claude/settings.json`, assuming the server is installed as `convalytics`:

```json
{
  "permissions": {
    "allow": [
      "mcp__convalytics__list_projects",
      "mcp__convalytics__get_usage",
      "mcp__convalytics__top_pages",
      "mcp__convalytics__top_referrers",
      "mcp__convalytics__pageviews_count",
      "mcp__convalytics__events_count",
      "mcp__convalytics__recent_events",
      "mcp__convalytics__list_funnels",
      "mcp__convalytics__get_funnel"
    ],
    "ask": [
      "mcp__convalytics__user_activity",
      "mcp__convalytics__weekly_digest",
      "mcp__convalytics__create_funnel",
      "mcp__convalytics__update_funnel",
      "mcp__convalytics__compute_funnel"
    ],
    "deny": [
      "mcp__convalytics__delete_funnel"
    ]
  }
}
```

## Remote posture

What an anonymous client saw at the remote endpoint, last 2026-10-22T14:51:20.677Z, unchanged since 2026-10-22T14:51:20.677Z. No credentials were sent and no tool was called. Values are shown as the endpoint returned them. Method: https://anlyon.dev/methodology#remote-posture

| Fact | Observed |
| --- | --- |
| Reachable | `yes` |
| HTTP status of an anonymous initialize | `200` |
| tools/list served without credentials | `yes` |
| Tools that change things, listed without credentials | `6` |
| Protocol version | `2025-06-18` |
| WWW-Authenticate on 401 | `not observed` |
| resource_metadata in WWW-Authenticate | `none` |
| RFC 9728 protected resource metadata | `none` |
| Authorization servers | `none` |
| Legacy HTTP+SSE transport | `no` |
| Dynamic client registration | `not observed` |
| Client ID metadata documents | `not observed` |

- **high** Tools that change things, listed to anyone ([unauth-remote-writes](https://anlyon.dev/methodology#unauth-remote-writes))

```untrusted-server-text
The endpoint served tools/list without credentials, and the list has 6 tools that change things (1 destructive, 5 write). Whether a call also works without credentials was not tested: tools are never called.

https://api.convalytics.dev/mcp: tools/list returned 15 tools to an anonymous client, including delete_funnel (destructive), user_activity (write), weekly_digest (write), create_funnel (write), update_funnel (write) and 1 more
```
