Skip to content

Commit 13c2a6d

Browse files
committed
fix(mcp): bugbot review on hardening PR
- Replace `as never` cast in negotiateProtocolVersion with `as readonly string[]` on the array — preserves TypeScript narrowing on the comparison while satisfying the readonly-tuple `.includes()` constraint properly. - Document the pg_advisory_xact_lock tradeoff: session-level locks (`pg_advisory_lock`) would release the connection earlier, but PgBouncer transaction-pooling mode breaks them. xact_lock is the correct choice for Sim's deployment; if pool pressure becomes real, the comment notes the Redlock escape hatch.
1 parent d67085d commit 13c2a6d

2 files changed

Lines changed: 12 additions & 1 deletion

File tree

apps/sim/app/api/mcp/serve/[serverId]/route.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ function negotiateProtocolVersion(rpcParams: unknown): string {
4646
rpcParams && typeof rpcParams === 'object' && 'protocolVersion' in rpcParams
4747
? (rpcParams as { protocolVersion?: unknown }).protocolVersion
4848
: undefined
49-
if (typeof requested === 'string' && SUPPORTED_PROTOCOL_VERSIONS.includes(requested as never)) {
49+
if (
50+
typeof requested === 'string' &&
51+
(SUPPORTED_PROTOCOL_VERSIONS as readonly string[]).includes(requested)
52+
) {
5053
return requested
5154
}
5255
return LATEST_PROTOCOL_VERSION

apps/sim/lib/mcp/oauth/storage.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,14 @@ export async function clearState(rowId: string): Promise<void> {
237237
* Node process holds concurrent callers.
238238
* 2) Postgres advisory transaction lock — blocks across processes; released
239239
* automatically when the transaction ends.
240+
*
241+
* Tradeoff: the connection is held for the duration of `fn()`, which includes
242+
* the SDK's OAuth HTTP refresh. Session-level locks (`pg_advisory_lock`) would
243+
* release the connection earlier, but they don't survive PgBouncer transaction
244+
* pooling — they're scoped to the underlying physical connection, which can be
245+
* swapped between statements. `pg_advisory_xact_lock` is the correct choice
246+
* here. If pool pressure becomes a real concern at scale, swap this for a
247+
* Redis-based distributed lock (Redlock) that doesn't pin a DB connection.
240248
*/
241249
const refreshLocks = new Map<string, Promise<unknown>>()
242250

0 commit comments

Comments
 (0)