> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aiola.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Hosted MCP Server

> Connect an OAuth-authenticated MCP client to project-scoped Aiola analytics, logs, feedback, and search data through one hosted endpoint.

The hosted server gives compatible MCP clients an always-online endpoint for every project on the signed-in account. It is mostly read-only; only App Log and Feedback status tools write data.

## Hosted versus workspace MCP

| Property          | Hosted MCP                                    | Workspace MCP Servers                                     |
| ----------------- | --------------------------------------------- | --------------------------------------------------------- |
| Settings location | Central Settings → MCP                        | Workspace Settings → MCP Servers                          |
| Scope             | All projects visible to the signed-in account | One selected workspace                                    |
| Runtime           | Aiola worker plus Supabase edge function      | Desktop-local bridge or configured `stdio`/`http` process |
| Authentication    | OAuth 2.1 bearer token                        | Local workspace configuration                             |
| Availability      | Requires Aiola Pro or an active trial         | Local bridge remains available to GUI Lifetime            |

See [MCP Servers](/core-features/mcp-servers) for local servers. Use [Connect Aiola through MCP](/guides/mcp-connector) for client setup.

## URL and transport

| Setting              | Exact value                                   |
| -------------------- | --------------------------------------------- |
| Name shown by Aiola  | `Aiola` (clients may use any name)            |
| Server URL           | `https://aiola.app/api/mcp`                   |
| Transport            | Streamable HTTP                               |
| Authentication       | OAuth 2.1 bearer token in `Authorization`     |
| MCP request method   | `POST`                                        |
| Accepted edge paths  | `/` and `/mcp` after function routing         |
| Request-body ceiling | `65536` bytes                                 |
| JSON-RPC batches     | Rejected with `400` and `batch_not_supported` |

## OAuth discovery

The edge function exposes protected-resource metadata at the public URL's well-known path:

```text theme={null}
GET https://aiola.app/.well-known/oauth-protected-resource/api/mcp
```

```json theme={null}
{
  "resource": "https://aiola.app/api/mcp",
  "authorization_servers": ["https://lhrsgoaselmgophvbqme.supabase.co/auth/v1"],
  "bearer_methods_supported": ["header"],
  "scopes_supported": ["openid", "email", "profile"],
  "resource_name": "Aiola",
  "resource_documentation": "https://docs.aiola.app/guides/mcp-connector"
}
```

Unauthenticated responses return `401` with a `WWW-Authenticate: Bearer` challenge containing the `resource_metadata` URL. The edge verifies the JWT issuer, `authenticated` audience, `ES256` or `RS256` signature, role, and UUID subject. OAuth client tokens must be demoted to the `aiola_mcp` role by the configured access-token hook.

## Subscription access

Every tool call reads the account's analytics-quota row before running. Access is granted when either condition is true:

| Eligible access | Rule                                        |
| --------------- | ------------------------------------------- |
| Pro             | Tier starts with `pro_`                     |
| Trial           | `trial_ends_at` is a valid future timestamp |

Tier `gui_lifetime` is explicitly excluded. A denied call returns the tool error `Aiola subscription required — https://aiola.app/pricing`.

Analytics tools that request analytics data also check the current usage period. When measured usage is greater than the finite quota, they return `Aiola analytics quota exceeded — https://aiola.app/pricing`. A failure to measure analytics usage fails open, while authentication, entitlement, ownership, and rate limiting still apply.

## Project scope

`list_projects` merges project names found in project keys, analytics sites, app-log groups, and feedback. Other tools accept a case-insensitive `project` name.

| Account state                                     | Resolution behavior                                         |
| ------------------------------------------------- | ----------------------------------------------------------- |
| Exactly one project                               | `project` may be omitted                                    |
| More than one project                             | `project` is required; omission returns the available names |
| Requested name absent                             | Call fails and returns the available names                  |
| Analytics-required tool on project without a site | Call fails with `Project <name> has no analytics site`      |

Queries apply both the authenticated user ID and resolved project name, or rely on the authenticated row-level-security policy where the schema requires it.

## Tool catalog

| Tool                        | Purpose                                                                                                                  | Access | Rate-limit cost |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------ | ------ | --------------- |
| `list_projects`             | List project names, domains, site IDs, creation dates, and available data types                                          | Read   | `1`             |
| `get_analytics_overview`    | Return dashboard summary, previous period, timeseries, acquisition, audience, events, journeys, revenue, and bot traffic | Read   | `12`            |
| `get_analytics`             | Query one analytics or bot-crawl pipe for a focused drill-down                                                           | Read   | `2`             |
| `get_analytics_definitions` | Return configured goals and saved funnels with computed funnel results                                                   | Read   | `6`             |
| `get_search_keywords`       | Return Google Search Console and Bing query/page metrics                                                                 | Read   | `3`             |
| `get_indexing_issues`       | Return Google indexing reason groups and Bing crawl issues                                                               | Read   | `6`             |
| `get_app_logs`              | List production error and warning groups                                                                                 | Read   | `1`             |
| `get_app_log_events`        | Return events, stack traces, breadcrumbs, and context for one log group                                                  | Read   | `1`             |
| `update_app_log_status`     | Change one or multiple log-group statuses                                                                                | Write  | `1`             |
| `get_feedback`              | List issue or feature-request submissions                                                                                | Read   | `1`             |
| `update_feedback`           | Change one feedback item's status                                                                                        | Write  | `1`             |

## Write operations

The only writes are status changes.

| Tool                    | Identifier                                     | Accepted statuses                                          | Additional limit        |
| ----------------------- | ---------------------------------------------- | ---------------------------------------------------------- | ----------------------- |
| `update_app_log_status` | UUID or `group_hash`; comma-separated for bulk | `open`, `in_progress`, `human_review`, `closed`, `ignored` | Maximum 100 identifiers |
| `update_feedback`       | Feedback UUID                                  | `open`, `in_progress`, `human_review`, `closed`, `ignored` | One item per call       |

Closing an App Log group sets `resolved_at` to the current timestamp; every other status clears `resolved_at`. Both updates constrain the write by authenticated user and resolved project.

## Redaction

`get_app_log_events` omits these top-level fields unless `include_request_data` is explicitly `true`:

```json theme={null}
[
  "request_headers",
  "request_body",
  "request_query",
  "user_ip",
  "user_email"
]
```

With request data excluded, nested values are also redacted when keys indicate authentication, tokens, cookies, sessions, secrets, passwords, credentials, API/private keys, signatures, OTP/PIN, CSRF, email, phone, SSN, passcodes, or card security codes. Strings are scanned for bearer tokens, JWTs, common prefixed API keys, email addresses, and long `eyJ…` token fragments. Replacements use `[redacted]`, and each event reports `_redacted` plus `_redacted_nested_values`.

Setting `include_request_data: true` returns the stored event rows without this MCP redaction pass and should be used only when the client needs that sensitive context.

## Rate limiting

All tools share weighted limits per authenticated user.

| Window          | Maximum weighted cost | Key scope           |
| --------------- | --------------------- | ------------------- |
| `60` seconds    | `120`                 | `mcp:<user-id>`     |
| `86400` seconds | `2000`                | `mcp:day:<user-id>` |

If the minute limiter or its backing RPC fails, the tool returns `rate limited — try again in a minute`. When the daily limit is exhausted, it returns `daily Aiola MCP limit reached — resets within 24 hours`.

## Worker and edge architecture

```text theme={null}
MCP client
  → https://aiola.app/api/mcp
  → aiola.app worker
  → Supabase /functions/v1/mcp
  → stateless Streamable HTTP MCP server
  → Supabase project data, Tinybird analytics, and search-provider APIs
```

The worker forwards only `authorization`, `content-type`, `accept`, `accept-encoding`, `mcp-session-id`, `mcp-protocol-version`, `last-event-id`, and `user-agent`. Cookies and forwarding headers are dropped. The upstream timeout is `120000` ms, and upstream responses pass through so OAuth challenges and MCP headers survive.

The edge server is stateless (`sessionIdGenerator` is undefined), accepts CORS methods `GET, POST, DELETE, OPTIONS`, and exposes a `GET /health` response of `{ "ok": true }`.

## Client compatibility

The in-app compatibility list contains exactly these clients:

| Client   |
| -------- |
| Claude   |
| ChatGPT  |
| Cursor   |
| Grok     |
| Grok bot |

Compatibility means the app presents these as examples for Streamable HTTP plus OAuth 2.1. Menu names and connection steps live in [Connect Aiola through MCP](/guides/mcp-connector), where they can be maintained independently of this server contract.
