generated: '2026-08-13' method: probed source: >- https://app.rybbit.io/.well-known/oauth-authorization-server (HTTP 200, application/json, fetched 2026-08-13) and https://app.rybbit.io/.well-known/oauth-protected-resource (HTTP 200) — both saved verbatim under well-known/. Scope semantics and the write-implies-read rule come from https://rybbit.com/docs/mcp. docs: https://rybbit.com/docs/mcp description: >- Rybbit runs an OAuth 2.1 authorization server for its hosted MCP endpoint. It is NOT declared in any OpenAPI securityScheme — Rybbit publishes no OpenAPI — so this scope list was read directly off the RFC 8414 / RFC 9728 discovery documents the API host serves anonymously. The same `resource:action` scope vocabulary also governs scoped API keys created via POST /api/user/api-keys with a `permissions` object, so these scopes are the provider's single permission model for both credentials. derive-oauth-scopes.py finds nothing here (0 oauth2 schemes in the specs); this file is deliberately probed, not derived, and must not be overwritten by that script. schemes: - name: RybbitMCP type: oauth2 source: well-known/rybbit-oauth-authorization-server.json issuer: https://app.rybbit.io resource: https://app.rybbit.io/api/mcp flows: - flow: authorizationCode authorizationUrl: https://app.rybbit.io/api/auth/mcp/authorize tokenUrl: https://app.rybbit.io/api/auth/mcp/token refreshUrl: https://app.rybbit.io/api/auth/mcp/token userinfo_endpoint: https://app.rybbit.io/api/auth/mcp/userinfo jwks_uri: https://app.rybbit.io/api/auth/mcp/jwks registration_endpoint: https://app.rybbit.io/api/auth/mcp/register dynamic_client_registration: true pkce: [S256] grant_types: [authorization_code, refresh_token] response_types: [code] token_endpoint_auth_methods: [client_secret_basic, client_secret_post, none] id_token_signing_alg: [RS256] bearer_methods: [header] rules: - '`write` implies `read` on the same resource.' - >- Scopes never elevate: organization admin/owner role requirements still apply after a scope check passes. - >- A grant (or key) that requests only the standard OIDC scopes is UNRESTRICTED — it acts with the full authority of the user. Restriction only happens when custom `resource:action` scopes are requested. - >- Consent is currently approve-or-deny as a whole; the requesting client chooses which scopes to ask for. - >- An out-of-scope call returns 403 {"error":"Insufficient scope","required":"goals:write"}. scope_count: 29 scopes: - {scope: openid, description: 'Standard OIDC scope. Requesting only OIDC scopes yields an unrestricted grant.', kind: oidc} - {scope: profile, description: 'Standard OIDC profile claims (name).', kind: oidc} - {scope: email, description: 'Standard OIDC email claims (email, email_verified).', kind: oidc} - {scope: offline_access, description: 'Issue a refresh token for long-lived agent sessions.', kind: oidc} - {scope: 'analytics:read', description: 'Read aggregate analytics — overview KPIs, time series, dimensional breakdowns, live visitors, errors, web vitals, retention, journeys.', kind: resource} - {scope: 'sessions:read', description: 'Read raw visitor sessions and individual session timelines.', kind: resource} - {scope: 'events:read', description: 'Read raw events and custom event names with counts.', kind: resource} - {scope: 'users:read', description: 'Read the person inventory and individual person profiles, traits, devices and locations.', kind: resource} - {scope: 'users:write', description: 'Identify a person, replace traits, and erase a person''s analytics data (GDPR erasure).', kind: resource} - {scope: 'goals:read', description: 'Read conversion goals and their conversion statistics.', kind: resource} - {scope: 'goals:write', description: 'Create, update and delete conversion goals.', kind: resource} - {scope: 'funnels:read', description: 'Read saved funnels and run ad-hoc funnel analysis.', kind: resource} - {scope: 'funnels:write', description: 'Save, update and delete funnels.', kind: resource} - {scope: 'dashboards:read', description: 'Read dashboard configuration.', kind: resource} - {scope: 'dashboards:write', description: 'Modify dashboard configuration.', kind: resource} - {scope: 'flags:read', description: 'Read feature flags.', kind: resource} - {scope: 'flags:write', description: 'Create and modify feature flags.', kind: resource} - {scope: 'experiments:read', description: 'Read experiments.', kind: resource} - {scope: 'experiments:write', description: 'Create and modify experiments.', kind: resource} - {scope: 'sites:read', description: 'Read site configuration and the list of accessible sites.', kind: resource} - {scope: 'sites:write', description: 'Create sites, change site configuration, and delete sites (admin/owner role also required).', kind: resource} - {scope: 'gsc:read', description: 'Read the Google Search Console integration data.', kind: resource} - {scope: 'gsc:write', description: 'Configure the Google Search Console integration.', kind: resource} - {scope: 'org:read', description: 'Read organization members, roles, site access and teams.', kind: resource} - {scope: 'org:write', description: 'Add members, change member site access, and create/update/delete teams (admin/owner role also required).', kind: resource} - {scope: 'replay:read', description: 'Read session replay recordings and their rrweb event streams.', kind: resource} - {scope: 'replay:write', description: 'Delete session replay recordings.', kind: resource} - {scope: 'sql:read', description: 'Read-only ClickHouse SQL against the site-scoped scoped_events table, plus the query schema.', kind: resource} - {scope: 'ingest:write', description: 'Write events into the ingestion pipeline. Advertised by the authorization server; no MCP tool currently exposes it.', kind: resource} x-evidence: - {url: 'https://app.rybbit.io/.well-known/oauth-authorization-server', http_status: 200, content_type: 'application/json'} - {url: 'https://app.rybbit.io/.well-known/openid-configuration', http_status: 200, content_type: 'application/json'} - {url: 'https://app.rybbit.io/.well-known/oauth-protected-resource', http_status: 200, content_type: 'application/json'} x-evidence-fetched: '2026-08-13'