fix: infer registry_name when MCP registry API returns empty values#181
Conversation
…icrosoft#180) All three client adapters (VS Code, Copilot, Codex) failed to resolve MCP registry packages because the API returns empty registry_name for most packages. Added _infer_registry_name() to each adapter that derives the package type from runtime_hint and package name patterns. Also added _extract_package_args() to the VS Code adapter to handle the package_arguments API format alongside legacy runtime_arguments. - VS Code adapter: added _infer_registry_name, _extract_package_args, -y flag for npx commands - Copilot adapter: added _infer_registry_name, updated _select_best_package - Codex adapter: added _infer_registry_name, updated _select_best_package - Tests: 15 new tests covering inference, arg extraction, real API format - Docs: added Package Type Inference section to integrations.md
There was a problem hiding this comment.
Pull request overview
Fixes MCP registry package resolution when the registry API returns empty registry_name values, by adding registry type inference in the client adapters so stdio-based MCP servers can still be selected/configured.
Changes:
- Added registry type inference (
_infer_registry_name) to VS Code, Copilot CLI, and Codex adapters and updated package selection to use inferred types. - Enhanced VS Code adapter formatting to support both
package_arguments(new API) andruntime_arguments(legacy), and added-yto npx args. - Added/updated unit tests and documented the new inference behavior in
docs/integrations.md.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
src/apm_cli/adapters/client/vscode.py |
Selects best package using inferred registry type; extracts args from new/legacy registry formats; adds npx -y; improves error messaging. |
src/apm_cli/adapters/client/copilot.py |
Uses inferred registry type for package selection/formatting when registry_name is empty. |
src/apm_cli/adapters/client/codex.py |
Uses inferred registry type for package selection/formatting when registry_name is empty. |
tests/unit/test_vscode_adapter.py |
Updates existing npx assertions and adds new test coverage for inference/extraction and real API-shaped payloads. |
tests/unit/test_runtime_args.py |
Updates expected npx args to include -y. |
tests/unit/test_env_variables.py |
Updates expected npx args to include -y. |
docs/integrations.md |
Documents package type inference behavior and supported package types per runtime. |
Comments suppressed due to low confidence (1)
src/apm_cli/adapters/client/codex.py:214
- Codex’s npm config path currently sets
commandtonpxbut buildsargsfromruntime_arguments+package_argumentswithout ensuring the npm package name is included. With the real MCP registry API, npm packages often provide onlypackage_arguments(e.g.['server','start']) and noruntime_arguments, which would producenpx server start(treatingserveras the package). Consider prepending the package name (and optionally-yfor non-interactive installs) whenregistry_nameis (inferred as)npmand the processed args don’t already include it.
registry_name = self._infer_registry_name(package)
package_name = package.get("name", "")
runtime_hint = package.get("runtime_hint", "")
runtime_arguments = package.get("runtime_arguments", [])
package_arguments = package.get("package_arguments", [])
env_vars = package.get("environment_variables", [])
# Resolve environment variables first
resolved_env = self._process_environment_variables(env_vars, env_overrides)
# Process arguments to extract simple string values
processed_runtime_args = self._process_arguments(runtime_arguments, resolved_env, runtime_vars)
processed_package_args = self._process_arguments(package_arguments, resolved_env, runtime_vars)
# Generate command and args based on package type
if registry_name == "npm":
config["command"] = runtime_hint or "npx"
# For npm packages, use runtime_arguments directly as they contain the complete npx command
config["args"] = processed_runtime_args + processed_package_args
# For NPM packages, also use env block for environment variables
You can also share your feedback on Copilot code review. Take the survey.
…e _infer_registry_name - VS Code & Codex adapters now always include the package name in npx args (e.g. npx -y @azure/mcp server start), filtering duplicates from legacy runtime_arguments that already contain it - Moved _infer_registry_name() to MCPClientAdapter base class to avoid identical copies across all three adapters - Codex adapter npm handler now includes -y flag for consistency - All 1039 tests pass
danielmeppiel
left a comment
There was a problem hiding this comment.
LGTM — most impactful of the three PRs. Fixes a real production bug where most MCP registry packages fail to install because registry_name is empty.
What I verified:
_infer_registry_name()placed inbase.py— correct, avoids triplication across adapters ✓- Inference chain is solid: explicit →
runtime_hint→ name pattern heuristics ✓ -yflag added to npx in VS Code + Codex adapters (Copilot adapter already had it) ✓_extract_package_args()normalizes bothpackage_arguments(current API) andruntime_arguments(legacy) — future-proofs against API evolution ✓- Generic
elif package and runtime_hint:fallback in VS Code adapter catches nuget/dotnet and other runtimes ✓ - Error messages now list available registries instead of generic "no package information" — good UX ✓
- 15+ tests including real API format coverage with actual registry response shapes ✓
docs/integrations.mdupdated ✓
Non-blocking observations:
- Pre-existing edge case: If a package list exists but the selected package has no
runtime_hintand doesn't match npm/docker/pypi,server_configwould be undefined when the env var block tries to reference it. The new generic fallback reduces this risk significantly, but aserver_config = {}initialization or an explicitelseguard would be belt-and-suspenders. Pre-existing though, not introduced here. - VS Code
_select_best_packagepriority is["npm", "pypi", "docker"]while Copilot/Codex use["npm", "docker", "pypi", "homebrew"]. This seems intentional but worth a comment explaining the rationale.
Merge order: PR 3 of 3. Rebase onto main after #178 merges.
Description
The MCP registry API returns empty
registry_namefor the majority of packages, causing all three client adapters to fail when resolving stdio-based MCP servers. This PR adds registry type inference to each adapter so package selection and configuration work regardless of whetherregistry_nameis populated.Fixes #180
Type of change
Changes
Root cause
The live MCP registry API (
api.mcp.github.com) returns"registry_name": ""for most packages. All three adapters (vscode.py,copilot.py,codex.py) match on this field directly in_select_best_package()and_format_server_config(), so package type resolution always fails.Solution
Added
_infer_registry_name()static method to each adapter that derives the package type through a fallback chain:registry_name(when non-empty)runtime_hintmapping (npx/npm→ npm,uvx/pip→ pypi,docker→ docker,dotnet→ nuget)@scope/name→ npm,ghcr.io/…→ docker,PascalCase.Name→ nuget,*.mcpb→ mcpb)Additionally for the VS Code adapter:
_extract_package_args()to normalize bothpackage_arguments(current API:{type, value}) andruntime_arguments(legacy:{is_required, value_hint})-yflag to npx commands for non-interactive installsFiles changed
src/apm_cli/adapters/client/vscode.py_infer_registry_name,_extract_package_args; updated selection and formattingsrc/apm_cli/adapters/client/copilot.py_infer_registry_name; updated_select_best_packageand registry_name usagesrc/apm_cli/adapters/client/codex.py_infer_registry_name; updated_select_best_packageand registry_name usagetests/unit/test_vscode_adapter.pyTestVSCodeInferRegistryName,TestVSCodeExtractPackageArgs,TestVSCodeRealApiFormat)tests/unit/test_runtime_args.py-yflag in npx argstests/unit/test_env_variables.py-yflag in npx argsdocs/integrations.mdTesting