Python SDK: launch_bridge randomly fails — token_urlsafe callback tokens starting with - are rejected by the bridge arg parser

Where does the bug appear (feature/product)?

Cursor SDK

Describe the Bug

AsyncClient.launch_bridge / Client.launch_bridge intermittently fails (~1.5% of launches) with:

Error: Bridge exited before discovery with status 1: cursor-sdk-bridge failed: Error: Missing value for --tool-callback-auth-token
at takeValue (…/cursor_sdk/_vendor/bridge/dist/bin/cursor-sdk-bridge.js:155:15)
at parseArgs (…:125:48)
at main (…:24:18)
It’s non-deterministic and depends only on a randomly generated token, so the same code “randomly crashes Python” with no caller-side cause.

Root cause

Two vendored components disagree on the - prefix:

The SDK mints callback bearer tokens with secrets.token_urlsafe(32) in both cursor_sdk/_tool_callback.py and cursor_sdk/_store_callback.py:

def new_auth_token() → str:
return secrets.token_urlsafe(32)
token_urlsafe uses the base64url alphabet [A-Za-z0-9
-], so a token can begin with -.

The token is passed positionally on the bridge CLI (_tool_callback.tool_callback_bridge_argv):

return [“–tool-callback-url”, endpoint.url,
“–tool-callback-auth-token”, endpoint.auth_token]
The bundled bridge’s takeValue treats any value starting with - as a missing flag value (cursor-sdk-bridge.js):

function takeValue(args, index, flag) {
const value = args[index];
if (value === undefined || value.startsWith(“-”)) {
throw new Error(Missing value for ${flag});
}
return value;
}
So whenever a generated token starts with -, the bridge aborts before discovery. (_ is also in the alphabet but isn’t rejected — only - triggers it.) The tool-callback server is created on every launch_bridge, so every launch is exposed; the store-callback token has the same latent flaw when enabled.

Measured frequency

import secrets
n = 100_000
rate = sum(secrets.token_urlsafe(32).startswith(“-”) for _ in range(n)) / n
print(rate) # ~0.0153 → ~1 in 65 launches

Steps to Reproduce

import asyncio, secrets
import cursor_sdk._tool_callback as tc
from cursor_sdk import AsyncClient

Force a token that starts with ‘-’ (token_urlsafe yields this ~1.5% of the time)

tc._new_auth_token = lambda: “-” + secrets.token_urlsafe(31)

async def main():
client = await AsyncClient.launch_bridge(workspace=“.”, local={“cwd”: “.”})
await client.aclose()

asyncio.run(main()) # → “Missing value for --tool-callback-auth-token”

Expected Behavior

launch_bridge should never fail based on the value of a randomly generated internal token.

Operating System

MacOS

Version Information

cursor-sdk==0.1.7 (Python)
bundled bridge cursor-sdk-bridge package version 1.0.0

For AI issues: which model did you use?

Opus 4.8

Additional Information

Suggested fix (any one)

Generate parser-safe tokens (e.g. regenerate while the token starts with -, or use hex/token_hex); or
Pass the value as --tool-callback-auth-token= (and the same for --store-callback-auth-token); or
Make the bridge’s takeValue accept the next token as a value when the flag is known to take one, rather than rejecting any --prefixed string.
Workaround

Monkeypatch the token generators before launching the bridge to avoid a leading -:

import secrets
import cursor_sdk._tool_callback as tc, cursor_sdk._store_callback as sc
def _safe_token():
t = secrets.token_urlsafe(32)
while t.startswith(“-”):
t = secrets.token_urlsafe(32)
return t
tc._new_auth_token = sc._new_auth_token = _safe_token

Does this stop you from using Cursor

No - Cursor works, but with this issue

hi @Natasha_Hirt Thank you very much for the thoughtful and detailed bug report. I was able to confirm this on our side, and your root-cause analysis is correct.

The Python SDK currently generates callback auth tokens with secrets.token_urlsafe(32), which can produce a token beginning with -. That token is then passed to the bridge as the value for --tool-callback-auth-token, and the bridge argument parser currently treats values beginning with - as missing flag values. That causes the bridge to exit before discovery.

We’re tracking this internally now. Until a fix ships, the workaround you shared is reasonable: regenerate or patch the callback to generate the token so it does not start with -.

Thanks again for the clean repro and suggested fixes. This was very helpful. We will keep you updated on the status of this bug fix.

Thank you @kevinn! Appreciate your responsiveness and look forward to the fix.