Skip to main content

Tokens

Every external request needs a bearer token. Tokens carry a scope, an optional connection allowlist, and an optional expiry. Tokens are stored hashed (SHA-256 + salt) at ~/Library/Application Support/TablePro/mcp-tokens.json with 0600 permissions. The plaintext is shown once at creation and never again.

Token shape

The prefix is shown in the token list so the user can identify a token without revealing the secret.

Scopes

A token’s permissions value maps to the MCP scopes the server enforces: What each token can do: Navigation tools (open_connection_window, open_table_tab, focus_query_tab, list_recent_tabs) need only tools:read. They surface UI but never bypass the connection allowlist or externalAccess: blocked. DROP and TRUNCATE always require an explicit confirmation phrase via confirm_destructive_operation, plus a token with tools:write (i.e. readWrite or fullAccess). There is no token permission that bypasses the phrase.

Connection allowlist

Each token can be limited to a subset of connections.
  • allowedConnectionIds = nil means all connections.
  • allowedConnectionIds = { uuid1, uuid2 } means only those.
A request that targets a connection outside the allowlist returns 403 forbidden before any per-connection check runs.

External access combination

The effective permission is MIN(token.scope, connection.externalAccess). A fullAccess or readWrite token cannot mutate data on a readOnly connection. A token’s reach is bounded by both itself and the connection’s externalAccess.

Creation

Tokens are created in three ways:
  1. Pairing flow (most common). See Pairing.
  2. Settings UI. Settings > Integrations > Authentication, then Generate Token. Pick name, scope, allowlist, expiry. The plaintext is shown once in a reveal sheet.
  3. AppleScript-style URL is not supported. Tokens are not exposed as a URL scheme action.
The plaintext format is tp_<base64url(32 bytes)>. The first 8 chars are the prefix.

Expiry

Optional. If set, the token stops authenticating at the expiry time. Expired requests return 401 unauthorized with message: "Token expired". Recommended values:
  • readWrite and fullAccess for human-driven extensions: 90 days.
  • readOnly for personal use: never.
  • CI or automation: 30 days, rotated.

Revocation

Settings > Integrations > Authentication lists all tokens with prefix, name, scope, allowlist, last-used time, and expiry. Each row has:
  • Revoke: marks the token inactive. Stays in the list with status Revoked. Cannot be reactivated.
  • Delete: removes the row entirely.
A revoked token returns 401 unauthorized immediately. The MCP server invalidates any cached session for the token within one second. After revoking a token used by an extension, the extension shows an “unauthorized” state on the next call. The user runs the pairing command again to mint a new token.

Audit log

Every authentication, every tool call, every resource read is recorded in ~/Library/Application Support/TablePro/mcp-audit.db with the token id (not the plaintext). The activity log view in Settings > Integrations > Activity Log shows: Entries are kept for 90 days, auto-pruned on app launch.

Rate limits

The MCP authenticator throttles failed token attempts. The bucket key is (client_address, principal_fingerprint), so a misbehaving bridge cannot lock out other principals on the same loopback address. A successful auth clears the bucket. During lockout the server returns HTTP 429 Too Many Requests with JSON-RPC code: -32000, message: "Rate limited".

What tokens cannot do

The token surface is the MCP tool catalog and the URL scheme. Anything not on those lists is not reachable.