perf(adapters): metadata-only availability probe — stop importing all 9 adapters on tools/list - #409
Merged
Conversation
… 9 adapters on tools/list isAdapterAvailable no longer imports and instantiates the adapter package; it asks an injectable PackageResolver whether the package (or a monorepo fallback build) is present on disk. Full import + factory instantiation stays where it belongs: the first real loadAdapter for a language. The first tools/list / create_debug_session / list_supported_languages call no longer drags every installed @debugmcp/adapter-* package into the heap (issue #401). Trade-off (as scoped in the issue): a present-but-broken package reports installed:true and surfaces its error at first load with the existing install-hint message. list_supported_languages' per-language getFactory for modes/validate is deliberately unchanged — an explicit informational call with a 30s validation cache. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #401
On the dist/source distribution, adapters load lazily per session — but the availability probe defeated that:
isAdapterAvailablewas literallytry { await loadAdapter() }, so the firsttools/list(andcreate_debug_session/list_supported_languagesvia the samegetSupportedLanguagesAsync()path) imported and instantiated all nine@debugmcp/adapter-*packages, permanently, into the heap of a server that may only ever debug Python.Change
PackageResolverseam onAdapterLoader(third constructor arg, mirroring the existingModuleLoaderseam).createDefaultPackageResolver():createRequire(import.meta.url).resolve(packageName)— presence via Node resolution, no module execution.ERR_PACKAGE_PATH_NOT_EXPORTEDcounts as installed (package present, ESM-only exports map).fs.accessover the loader's two existing monorepo fallback paths.isAdapterAvailable: cache-hit short-circuit (a genuinely-loaded factory) → resolver probe. No import, no factory instantiation.loadAdapteris untouched — full import + instantiation happen at the first real use of a language (AdapterRegistry.create()).listAvailableAdaptersmetadata comes from its static known-adapter table as before; the live-factoryattachrefinement still applies when a factory was actually loaded.Scope decisions (as discussed in the issue)
list_supported_languages' per-languagegetFactory()for modes + toolchainvalidateis deliberately unchanged: it's an explicit informational call with a 30s validation cache, and skipping the factory would silently turnlaunch.availablefrom a real toolchain probe into assumed-true. The issue's stated goal — bounding "the server that answeredinitializeand onetools/list" — is met by fixing the probe.installed: trueand surfaces its error at first load, with the existing install-hint message.Measured (mem-bench, this machine, Windows)
node scripts/mem-bench.mjs --target dist --scenario idle,tools, median RSS over 5 trials. The metric for this issue is the tools/list step cost (after-tools-list − after-initialize):(The absolute after-initialize difference is #400's lazy transports, which this branch is rebased on; the before-baseline predates it.)
Tests
metadata-only availability probedescribe: probe returns availability without anymoduleLoader.loadcall; cache short-circuit skips re-probing;listAvailableAdapterscovers all 9 with zero imports.createDefaultPackageResolverdescribe: resolve-success, exports-map-rejection-as-installed, fs fallback (platform-safe file URLs), nothing-resolves.packages/*/distbeing built (real fs hits).npm testgreen,npm run lintclean.🤖 Generated with Claude Code