Unified · Split
| @@ -22,7 +22,10 @@ export const protectedResourceMetadataResponse = (organizationId: string | null · 21 unmodified lines | ||
| 22 | 22 | resource: resourceUrlFor(organizationId), |
| 23 | 23 | authorization_servers: [AUTHKIT_DOMAIN], |
| 24 | 24 | bearer_methods_supported: ["header"], |
| 25 | − scopes_supported: [], | |
| 25 | + // Spec-faithful clients (OpenCode, mcporter) request exactly what is | |
| 26 | + // advertised here; without offline_access they get no refresh token and | |
| 27 | + // silently sign out at every access-token expiry. | |
| 28 | + scopes_supported: ["openid", "profile", "email", "offline_access"], | |
| 26 | 29 | }); |
| 27 | 30 | |
| 28 | 31 | export const authorizationServerMetadataResponse: Effect.Effect<Response> = Effect.tryPromise({ |
| @@ -150,7 +150,10 @@ scenario( · 149 unmodified lines | ||
| 150 | 150 | resource: new URL("/mcp", target.baseUrl).toString(), |
| 151 | 151 | authorization_servers: [expect.any(String)], |
| 152 | 152 | bearer_methods_supported: ["header"], |
| 153 | − scopes_supported: [], | |
| 153 | + // offline_access MUST stay advertised: spec-faithful clients request | |
| 154 | + // exactly this list, and it is what earns them a refresh token (the | |
| 155 | + // OpenCode daily re-auth bug). | |
| 156 | + scopes_supported: ["openid", "profile", "email", "offline_access"], | |
| 154 | 157 | }); |
| 155 | 158 | |
| 156 | 159 | // The advertised server must itself be discoverable — that is what lets |