Documentation Index
Fetch the complete documentation index at: https://docs.tablepro.app/llms.txt
Use this file to discover all available pages before exploring further.
Pairing
Pairing is how an extension gets a TablePro token without the user copying and pasting one. The user runs aPair with TablePro command in the extension, picks scopes and connections inside TablePro, and the extension receives a token over a Raycast deep link callback.
The flow is PKCE-flavored: the extension generates a verifier, hashes it into a challenge, and the token is only released after the verifier is presented. This prevents another app on the same machine from intercepting the redirect and stealing the token.
Sequence
Step by step
1. Extension generates a verifier and challenge
2. Extension opens the pair deep link
3. TablePro shows the approval sheet
The user sees:- The client name from the request.
- A scopes radio (defaults to the requested scope, downgradeable).
- A connections multi-select (defaults to all unless
connection-idswas provided). - An expiry picker (defaults to never).
4. TablePro generates a token and a one-time code
On approval, TablePro callsMCPTokenStore.generate(...) to mint a token, then stores a pending exchange:
5. TablePro redirects with the code
TablePro opens theredirect URL with NSWorkspace.shared.open(...). The encoding depends on the redirect scheme:
raycast://...: TablePro appends?context={"code":"<uuid>"}(URL-encoded JSON). Raycast parsescontextand passes it to the receiving command asLaunchProps.launchContext. This matches Raycast’s documented launch-context convention.- Anything else (
http://127.0.0.1:<port>/callback, custom schemes): TablePro appends?code=<uuid>as a flat query parameter. Standard OAuth-callback shape.
6. Extension exchanges the code
The extension reads the MCP port from~/Library/Application Support/TablePro/mcp-handshake.json, then:
7. TablePro validates and returns the token
Server-side check:403.
8. Extension stores the token
updateCommandMetadata or write to the password preference. Tokens stored in Raycast preferences live in the macOS Keychain.
Security properties
| Property | How |
|---|---|
| Token is never in the URL | The token is fetched over localhost HTTP, not embedded in a deep link. |
| Redirect interception is harmless | A malicious app that intercepts the code cannot exchange it without the verifier. |
| Code is single-use | Successful exchange or 5-minute expiry deletes the pending exchange. |
| Plaintext token is not persisted by TablePro | Only the SHA-256 hash plus salt is saved to mcp-tokens.json. |
| User sees and approves scopes | The sheet shows what was requested, what is granted, and which connections. |
| User can revoke any time | Settings > Integrations > Authentication > Revoke. |
Errors
| Code | Meaning |
|---|---|
403 challenge mismatch | The verifier does not hash to the stored challenge. |
404 pairing code | The code does not exist or has already been exchanged. |
410 expired | The pending exchange is older than 5 minutes. |
auth category with outcome denied.
Implementing pairing in another extension
The flow is not Raycast-specific. Cursor, Claude Desktop, or any custom client can use it. Requirements:- Generate a verifier and challenge.
- Open
tablepro://integrations/pair?...with a deep link callback URL the OS can route back to the extension. - Read the MCP port from the handshake file.
- POST
{ code, code_verifier }to/v1/integrations/exchange. - Store the returned token in OS Keychain.
http://127.0.0.1:<port>/callback as the redirect.