Hotfix: makes 2.0.2's OAuth path actually finish. The 2.0.2 design assumed all manually-registered Productboard OAuth apps were Public Clients (PKCE-only, no secret). They are not: PB's admin UI issues a client_secret for every manually-registered app, with no Public Client / PKCE-only option. Authorize succeeds but token exchange fails with HTTP 400.
Added
PRODUCTBOARD_OAUTH_CLIENT_SECRETenv var. When set, included inPOST /oauth2/tokenfor both the initial authorization-code exchange (inoauth-setup.ts) and every subsequent refresh (inoauth-refresh.ts). Stripped of CR/LF and trimmed before use. Not persisted totokens.json— re-read from env at each refresh, so the secret stays in whatever store the consumer chose (tarsroles.json, Claude Code MCP config env block, shell init, etc.).resolveClientSecret()helper insrc/auth/types.ts. Lives intypes.ts(notresolver.ts) sooauth-refresh.tscan import it without creating aresolver↔refreshcircular import.
Changed
- 404 error message in
registerClient()now instructs the user to copy bothclient_idandclient_secretfrom PB admin UI and export both env vars. Previously instructed only onclient_id. SetupOptions.clientSecretfield added; threaded throughHandlerContextto the token-exchange body.
Known issues (still upstream)
- Productboard's
POST /oauth2/registerstill returns HTTP 404 (Kong gateway, no backend wired). When upstream is fixed, the dynamic-registration path will activate automatically and produce a true Public Client — at which pointPRODUCTBOARD_OAUTH_CLIENT_SECRETbecomes optional. The code already handles both cases (omitsclient_secretfrom the request when undefined).
Migration notes for callers
- Nothing breaks for PAT users. PAT mode is unaffected.
- Dr.Max users on tars: after
roles.jsonis bumped to 2.0.3,PRODUCTBOARD_OAUTH_CLIENT_SECRETmust be added to the productboard MCP's env block alongside the existing config. Without it, token exchange returns HTTP 400. - Non-Dr.Max consumers: must register their own OAuth app in PB admin UI and set both
PRODUCTBOARD_OAUTH_CLIENT_IDandPRODUCTBOARD_OAUTH_CLIENT_SECRET. The 404 error message now walks through both. - Existing OAuth installations from 2.0.2: delete
tokens.json(the 2.0.2 attempt never succeeded) and restart with the secret env var set.