microsoft / microsoft/apm

[BUG] Plugins whose manifest is .codex-plugin/plugin.json lose their MCP servers (typed skill_bundle)

Open
#2,992 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area/marketplace area/mcp-config area/multi-target status/accepted theme/portability triage/recommended type/bug
Dominant language
Python
Stars
3.8k
Forks
362
Avg merge
1d 17h
Merged PRs (30d)
132

Description

Describe the bug

apm does not recognise Codex's plugin manifest, .codex-plugin/plugin.json. A marketplace plugin whose only manifest sits there — for example one that declares "mcpServers": "./.mcp.codex.json" — is installed as a skill_bundle: its skills and hooks integrate, but none of the MCP servers its manifest declares is registered with any runtime, and none appears in the lockfile's mcp_servers or mcp_configs.

Where, in the 0.30.0 source

  • utils/helpers.py, find_plugin_json: the manifest lookup checks plugin.json, .github/plugin/plugin.json, .claude-plugin/plugin.json and .cursor-plugin/plugin.json. .codex-plugin/plugin.json is not among them, and the source contains no reference to .codex-plugin anywhere.
  • models/format_detection.py, ClaudePluginDetector and NormalizationPlanner.plan: with none of those manifests present, nested skills/<name>/SKILL.md resolves the package to SKILL_BUNDLE.
  • deps/plugin_parser.py, _extract_mcp_servers: resolves mcpServers (and the .mcp.json auto-discovery), substitutes ${CLAUDE_PLUGIN_ROOT}, and injects the result as _mcp_deps — on the MARKETPLACE_PLUGIN path only.
  • Observed on a user-scope install: such a plugin is locked with package_type: skill_bundle, its skills and hooks are deployed, and no MCP server it declares is registered.

To Reproduce

Derived from the source above; not executed as a standalone script. A plugin laid out as:

example-plugin/
├── .codex-plugin/plugin.json   {"name": "example-plugin", "skills": "./skills", "hooks": "./hooks/hooks.json", "mcpServers": "./.mcp.codex.json"}
├── .mcp.codex.json             {"mcpServers": {"example": {"command": "npx", "args": ["-y", "example-mcp"]}}}
├── hooks/hooks.json
└── skills/example/SKILL.md

published through a marketplace and installed with apm install example-plugin@<marketplace> -g, is locked as package_type: skill_bundle and registers no example MCP server. The same manifest placed at .claude-plugin/plugin.json or at the root as plugin.json makes the package a marketplace_plugin, whose mcpServers are resolved and registered.

Expected behavior

.codex-plugin/plugin.json is recognised as a plugin manifest alongside the root, GitHub, Claude and Cursor locations, so a Codex-format plugin's mcpServers are registered for every target, as any other plugin's are.

Environment

  • OS: macOS, Apple Silicon
  • APM: Homebrew binary, Agent Package Manager (APM) CLI version 0.30.0
  • Codex CLI 0.154.0 (whose binary carries the .codex-plugin manifest location)
  • Scope: user (-g)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in utils/helpers.py at find_plugin_json, then trace models/format_detection.py through ClaudePluginDetector and NormalizationPlanner.plan. Read deps/plugin_parser.py, especially _extract_mcp_servers, and compare the existing manifest paths with the .codex-plugin path. Done means the sample plugin is classified as a marketplace_plugin and its MCP server appears in the lockfile and is registered for each target.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli, tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.