Skip to content

Commit d74d48d

Browse files
committed
chore(mcp): add debug logging for pool hit/miss/eviction observability
1 parent 65bd1f3 commit d74d48d

1 file changed

Lines changed: 18 additions & 13 deletions

File tree

apps/sim/lib/mcp/connection-pool.ts

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,11 @@ export class McpConnectionPool {
107107
private async tryReuse(entry: PoolEntry): Promise<PoolEntry | null> {
108108
const now = Date.now()
109109
if (now - entry.createdAt > MAX_CONNECTION_AGE_MS) {
110-
this.retire(entry)
110+
this.retire(entry, 'max age reached')
111111
return null
112112
}
113113
if (!entry.client.getStatus().connected) {
114-
this.retire(entry)
114+
this.retire(entry, 'not connected')
115115
return null
116116
}
117117
if (now - entry.lastLivenessCheckAt > LIVENESS_TTL_MS) {
@@ -123,11 +123,12 @@ export class McpConnectionPool {
123123
// ping await; don't hand out a connection that's already closing.
124124
if (entry.retired) return null
125125
if (!alive) {
126-
this.retire(entry)
126+
this.retire(entry, 'liveness ping failed')
127127
return null
128128
}
129129
entry.lastLivenessCheckAt = now
130130
}
131+
logger.debug(`Reusing pooled MCP connection ${entry.key}`)
131132
return entry
132133
}
133134

@@ -164,6 +165,9 @@ export class McpConnectionPool {
164165
this.entries.set(params.key, entry)
165166
client.onClose(this.makeCloseHandler(entry))
166167
this.ensureIdleCheck()
168+
logger.debug(
169+
`Established and pooled MCP connection ${params.key} (${this.entries.size}/${MAX_POOL_SIZE})`
170+
)
167171
return entry
168172
})()
169173

@@ -176,30 +180,34 @@ export class McpConnectionPool {
176180
private async release(entry: PoolEntry, poison: boolean): Promise<void> {
177181
entry.borrowers = Math.max(0, entry.borrowers - 1)
178182
entry.lastActivityAt = Date.now()
179-
if (poison) this.retire(entry)
183+
if (poison) this.retire(entry, 'poisoned by failed operation')
180184
await this.closeIfIdle(entry)
181185
}
182186

183187
/** Own scope so the handler captures only `entry` (never the create params / secrets). */
184188
private makeCloseHandler(entry: PoolEntry): () => void {
185189
return () => {
186-
if (this.entries.get(entry.key) === entry) this.retire(entry)
190+
if (this.entries.get(entry.key) === entry) this.retire(entry, 'transport closed')
187191
}
188192
}
189193

190194
/** Remove `entry` from the pool so no new borrower takes it; close it once idle. */
191-
private retire(entry: PoolEntry): void {
195+
private retire(entry: PoolEntry, reason: string): void {
192196
if (!entry.retired) {
193197
entry.retired = true
194198
if (this.entries.get(entry.key) === entry) this.entries.delete(entry.key)
199+
logger.debug(`Retiring pooled MCP connection ${entry.key}: ${reason}`, {
200+
borrowers: entry.borrowers,
201+
poolSize: this.entries.size,
202+
})
195203
}
196204
void this.closeIfIdle(entry)
197205
}
198206

199207
private async closeIfIdle(entry: PoolEntry): Promise<void> {
200208
if (!entry.retired || entry.borrowers > 0 || entry.closing) return
201209
entry.closing = true
202-
logger.info(`Closing pooled MCP connection ${entry.key}`)
210+
logger.debug(`Closing pooled MCP connection ${entry.key}`)
203211
await entry.client.disconnect().catch((error) => {
204212
logger.warn(`Error disconnecting pooled MCP connection ${entry.key}:`, error)
205213
})
@@ -211,10 +219,7 @@ export class McpConnectionPool {
211219
// instead of pooling a connection built against the now-stale config.
212220
this.serverGenerations.set(serverId, (this.serverGenerations.get(serverId) ?? 0) + 1)
213221
for (const entry of this.entries.values()) {
214-
if (entry.serverId === serverId) {
215-
logger.info(`Evicting pooled MCP connection ${entry.key}: ${reason}`)
216-
this.retire(entry)
217-
}
222+
if (entry.serverId === serverId) this.retire(entry, reason)
218223
}
219224
}
220225

@@ -225,7 +230,7 @@ export class McpConnectionPool {
225230
if (!lru || entry.lastActivityAt < lru.lastActivityAt) lru = entry
226231
}
227232
// Retiring a still-borrowed LRU frees the map slot now; its socket closes on release.
228-
if (lru) this.retire(lru)
233+
if (lru) this.retire(lru, 'pool at capacity (LRU)')
229234
}
230235

231236
private ensureIdleCheck(): void {
@@ -234,7 +239,7 @@ export class McpConnectionPool {
234239
const now = Date.now()
235240
for (const entry of this.entries.values()) {
236241
if (entry.borrowers === 0 && now - entry.lastActivityAt > IDLE_TIMEOUT_MS)
237-
this.retire(entry)
242+
this.retire(entry, 'idle timeout')
238243
}
239244
if (this.entries.size === 0 && this.idleCheckTimer) {
240245
clearInterval(this.idleCheckTimer)

0 commit comments

Comments
 (0)