version: 1
name: Zola
slug: zola
summary: >-
  Zola wedding planning tools for Claude — vendors, budget, guests, seating,
  events, registry, inquiries, and more
#
# Hosting note (a comment, not user-facing summary text): this is a
# BROWSER-BRIDGE MCP — it reaches its site through the user's signed-in
# tab via the fetchproxy bridge. A bridged registration also needs runtime
# `fly-shared`, `bridge: true` and a `bridgePortEnv`, which are registration
# fields this manifest has no schema for (set them over the control API).
# `state.dataDir` below is required for `bridge`.
env:
  - name: ZOLA_REFRESH_TOKEN
    secret: true
    required: false
    help: >-
      Zola refresh token JWT (~1 year lifetime). Optional — when unset, the MCP
      falls back to ContextMint Bridge, the browser extension, to read the
      `usr` cookie from your signed-in zola.com tab.
  - name: ZOLA_ACCOUNT_ID
    required: false
    help: >-
      Overrides the account id normally read from GET /v3/users/me/context. Set
      it only to pin a specific account.
  - name: ZOLA_DISABLE_FETCHPROXY
    required: false
    help: >-
      Set to '1' to opt out of the fetchproxy browser fallback (headless / CI).
      With it set and no ZOLA_REFRESH_TOKEN, auth is a hard error unless a
      previous bootstrap already cached a token — reading that file is not
      opening a browser, so the cache stays readable.
  - name: ZOLA_REGISTRY_ID
    required: false
    help: >-
      Overrides the registry id normally read from the same context call.
  - name: ZOLA_SESSION_TOKEN
    secret: true
    required: false
    help: >-
      A seed session token (JWT). The client refreshes it about five minutes
      before its exp, so this is a starting point rather than a long-lived
      credential.
  - name: ZOLA_TOKEN_CACHE
    required: false
    help: >-
      Set to 'false' to disable the on-disk refresh-token cache and ask the
      browser on every start. Defaults to enabled. Inert when
      ZOLA_REFRESH_TOKEN is set — there is no bootstrap to skip.
  - name: ZOLA_TOKEN_FILE
    required: false
    help: >-
      Absolute path for the refresh-token cache file. Defaults to
      $MCP_DATA_DIR/.zola-mcp/refresh-token.json, else the same path under
      $HOME.
  - name: ZOLA_WEDDING_ID
    required: false
    help: >-
      Overrides the wedding id normally read from the same context call.
state:
  dataDir: true
  reason: >-
    Two things live here. The fetchproxy identity is at
    $HOME/.fetchproxy/identity/<name>.json and the pair code derives from it —
    without a persistent $HOME every cold start mints a fresh identity and
    re-prompts pairing in the browser, and the API refuses bridge without it.
    The bootstrapped refresh token is cached at
    $MCP_DATA_DIR/.zola-mcp/refresh-token.json (0600), which matters most on
    that same path: the `usr` cookie it holds is valid for ~a year, so with the
    cache a cold start needs no browser at all, and without it every cold start
    and every 30-minute session expiry goes back to the bridge — on a
    scale-to-zero machine, constantly.
egress:
  allow:
    # Only hosts the SERVER process actually fetches. Hosts that appear
    # solely in a URL this server BUILDS and returns are excluded.
    #
    # The bridge here is BOOTSTRAP-ONLY: `@fetchproxy/bootstrap` lifts the
    # `usr` cookie from the signed-in tab (or ZOLA_REFRESH_TOKEN skips it),
    # and every API call after that is a direct dial from this process
    # (src/client.ts) — fetchproxy is not in the hot path in any mode.
    - mobile-api.zola.com   # POST /v3/sessions/refresh + every tool call
    - www.zola.com          # reconcile_registry reads the server-rendered
                            # /registry/{key} page (src/registry-collection.ts)
    # NOT `zola.com` (apex): it is only the bootstrap cookie domain and the
    # sign-in hint; the process never dials it, and the apex 301s TO www,
    # never the reverse. Neither host redirects on the paths used.
examples:
  - prompt: How many guests have RSVP'd yes, no, or not at all for each of our wedding events?
    note: Reads the per-event RSVP summary.
  - prompt: Summarize our wedding budget — what we've budgeted, spent, and paid so far, by item.
  - prompt: Which guests still don't have a seat assigned on our seating chart?
    note: Read-only; lists unseated guests.
