@@ -66,6 +66,8 @@ interface PoolEntry {
6666export class McpConnectionPool {
6767 private entries = new Map < string , PoolEntry > ( )
6868 private pending = new Map < string , Promise < PoolEntry > > ( )
69+ /** Per-server counter bumped by `evictServer`; an in-flight create built against an older value is retired on completion. */
70+ private serverGenerations = new Map < string , number > ( )
6971 private idleCheckTimer : ReturnType < typeof setInterval > | null = null
7072 private disposed = false
7173
@@ -94,7 +96,10 @@ export class McpConnectionPool {
9496 const reusable = await this . tryReuse ( current )
9597 if ( reusable ) return reusable
9698 }
97- return this . createEntry ( params )
99+ const created = await this . createEntry ( params )
100+ // Evicted (config edit/delete) mid-create → don't borrow the stale connection.
101+ if ( created . retired && ! this . disposed ) return this . resolveEntry ( params )
102+ return created
98103 }
99104
100105 /** Return `entry` if in-age, connected, and live; else retire it and return null. */
@@ -132,6 +137,7 @@ export class McpConnectionPool {
132137 if ( inFlight ) return inFlight
133138
134139 const creation = ( async ( ) => {
140+ const generation = this . serverGenerations . get ( params . serverId ) ?? 0
135141 const client = await params . create ( )
136142 const now = Date . now ( )
137143 const entry : PoolEntry = {
@@ -145,7 +151,9 @@ export class McpConnectionPool {
145151 retired : false ,
146152 closing : false ,
147153 }
148- if ( this . disposed ) {
154+ // Disposed, or the server was evicted (config edit/delete) while connecting:
155+ // don't pool a connection built against the old config.
156+ if ( this . disposed || ( this . serverGenerations . get ( params . serverId ) ?? 0 ) !== generation ) {
149157 entry . retired = true
150158 void client . disconnect ( ) . catch ( ( ) => { } )
151159 return entry
@@ -197,6 +205,9 @@ export class McpConnectionPool {
197205
198206 /** Retire every connection for a server (all users) — config changed or deleted. */
199207 async evictServer ( serverId : string , reason : string ) : Promise < void > {
208+ // Bump first so an in-flight create for this server retires on completion
209+ // instead of pooling a connection built against the now-stale config.
210+ this . serverGenerations . set ( serverId , ( this . serverGenerations . get ( serverId ) ?? 0 ) + 1 )
200211 for ( const entry of this . entries . values ( ) ) {
201212 if ( entry . serverId === serverId ) {
202213 logger . info ( `Evicting pooled MCP connection ${ entry . key } : ${ reason } ` )
0 commit comments