What cancellation contract should MCP client factories guarantee? #1034
PierrunoYT
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Contract question
internal/mcp/registry.gostarts each configured server concurrently. It calls the pluggable client factory in a goroutine, returns a timeout result when the configured duration expires, cancels that server context, and starts a background reaper waiting for the factory result so any late client can be closed.This works for current built-in factories that honor context cancellation. If a custom/test/plugin-supplied factory ignores context forever, both the factory call and its reaper remain blocked after startup has moved on. The leak is bounded per timed-out attempt, but there is no independent way for the registry to terminate work it does not own.
Audit context: finding
CON-01atmainrevision1b5db1765672820caac1684b168c9898b5ba3593, primarilyinternal/mcp/registry.goaround lines 115-143.No leak from a current built-in MCP transport was reproduced, so this is a contract/ownership question rather than a bug report.
Existing strengths
These properties should remain.
Options
ctx.Done(). Add a context-ignoring fake to define expected diagnostics, but accept that Go cannot force-stop a violating goroutine.Questions for maintainers
Any implementation should preserve deterministic registration, best-effort startup, bounded stderr/output, cancellation of built-ins, and race coverage.
Full audit detail: https://github.com/PierrunoYT/zero/blob/audit/codebase-audit-2026-09-08/docs/audit/CONCURRENCY_AUDIT.md#con-01--mcp-timeout-may-leave-a-goroutine-if-a-factory-ignores-context
All reactions