Packaging
Packaging & marketplaces#
There are two ways to ship a connector: install it directly with your branded package/bin, or emit a marketplace / extension bundle others install through their host's own plugin flow. The framework package command renders the bundle for any of nine host ecosystem formats (the portable Agent Plugins 1.0.0 agent-plugin package — the default, and the single source of truth for Codex, GitHub Copilot CLI, VS Code / JetBrains Copilot, Kiro and Hermes — plus eight host-native bundles) — plus two official MCP standard artifacts (a registry server.json and an mcpb bundle) that plug your real upstream server into the cross-vendor distribution graph.
The branded package CLI detects every installed host and writes each one's native MCP registration, hook config, and content files in place. The connector lives where you ran it — ideal for your own machine / CI.
Emit a self-contained marketplace / extension bundle others install through their host's plugin flow. The bundle re-renders the SAME content + hooks + serve-wrapped MCP entry, so a marketplace-installed connector behaves exactly like a direct install — telemetry included.
The package command#
npx @ken-jo/agent-connector package --connector ./agent-connector.config.mjs [--format <fmt>] [--out <dir>] [--dry-run]. Packaging emits distribution artifacts, so it is intentionally a framework tool rather than a branded MCP lifecycle command. If you already keep the framework CLI globally installed, use agent-connector package --connector ./agent-connector.config.mjs. The bundle is written under --out (default <cwd>/dist-plugin); --dry-run computes the file tree without writing.
- Default
--format agent-plugin. Omitting--formatemits the Agent Plugins 1.0.0 bundle. The retiredcodex-plugin/copilot-pluginnames still parse and resolve to it with a deprecation line. --format allemits EVERY feasible format, each into its own<out>/<format>/subdir (no collisions), printing per-format install instructions.- An invalid
--formatexits2withinvalid --format "…" (expected one of: …, or "all").
# default format (agent-plugin — the Agent Plugins 1.0.0 bundle) → <cwd>/dist-plugin
npx @ken-jo/agent-connector package --connector ./agent-connector.config.mjs
# pick a format + output dir; preview without writing
npx @ken-jo/agent-connector package --connector ./agent-connector.config.mjs --format gemini-extension --out ./dist --dry-run
# emit EVERY feasible format, each into <out>/<format>/
npx @ken-jo/agent-connector package --connector ./agent-connector.config.mjs --format all --out ./dist
# an unknown format exits 2
npx @ken-jo/agent-connector package --connector ./agent-connector.config.mjs --format bogus # → invalid --format "bogus" (exit 2)
# if you already keep the framework CLI globally installed, drop the npx package prefix:
agent-connector package --connector ./agent-connector.config.mjs --format all --out ./distHost formats + standard artifacts#
For each format: the --format value, the target platform(s) it serves, the manifest file(s) it emits, and the user install command. The command / skill / subagent markdown is rendered through the same shared claude-code renderers the live adapters write with, so an installed plugin and the branded direct install produce byte-identical content files.
| --format | Target platform(s) | Manifest emitted | Install command |
|---|---|---|---|
agent-plugindefault #1 | Agent Plugins 1.0.0 — the DEFAULT and the single source of truth for every spec-speaking host: Codex · GitHub Copilot CLI · VS Code / JetBrains Copilot · Kiro · Hermes · Cursor · OpenClaw · … | plugin.json ($schema + name + extensions; root) + mcp.json ($schema + mcpServers: stdio | streamable-http | sse) + skills/<n>/SKILL.md + bin/agent-connector.mjs (portable launcher) + com.github.copilot/{hooks/hooks.json, commands/, agents/<n>.agent.md} + com.openai/hooks/hooks.json + README.md; local catalogs at <out>/.claude-plugin/marketplace.json and <out>/.agents/plugins/marketplace.json | copilot plugin marketplace add <out> · copilot plugin install <id>@agent-connector — or — codex plugin marketplace add <out> · codex plugin add <id>@agent-connector (both driven end-to-end by `install --method marketplace --targets codex,copilot-cli`; VS Code auto-discovers the CLI install). To share: push <out>/<id> to a git repo and install from source (VS Code: “Chat: Install Plugin From Source”; Kiro / Hermes / others per https://agent-plugins.org/compatible-clients).The open, vendor-neutral spec (agent-plugins.org — Vercel-led with AWS, Cursor, GitHub, Microsoft, OpenAI). Portable core = skills + MCP; hooks/commands/subagents are client-specific and ride per client-extension namespace (com.github.copilot/ for Copilot CLI + VS Code + JetBrains; com.openai/ for Codex, pointed at by the manifest's extensions block) — clients ignore namespaces they do not own. NO absolute path in the portable surfaces (the spec forbids it): the serve-wrapper and Copilot hooks run `node ${PLUGIN_ROOT}/bin/agent-connector.mjs`, a bundled launcher resolving home binary → PATH → npx. The only bundle that also carries REMOTE servers (streamable-http / sse). The retired codex-plugin / copilot-plugin names resolve here. |
claude-plugin#2 | Claude Code · OpenClaw · OMP | .claude-plugin/plugin.json + .claude-plugin/marketplace.json (+ commands/, agents/, skills/<n>/SKILL.md, hooks/hooks.json, .mcp.json) | /plugin marketplace add <out> · /plugin install <id>@agent-connectorThe Claude-family bundle (driven end-to-end by `install --method marketplace --targets claude-code`). plugin.json carries a $schema; the marketplace catalog is the object-owner shape. |
factory-plugin#3 | Droid (Factory) | .factory-plugin/plugin.json + droids/ + mcp.json + marketplace.json (git-repo catalog at the repo root) | droid plugin marketplace add <out> · droid plugin install <id>@agent-connector (driven by `install --method marketplace --targets droid`; driver shipped, pending a live host)Subagents go in droids/ (not agents/); MCP filename is mcp.json; plugin.json pins version + author. The marketplace catalog is marketplace.json at the bundle ROOT (factory shape). |
gemini-extension#4 | Gemini CLI | gemini-extension.json (inline mcpServers + contextFileName) + commands/<n>.toml + agents/, skills/, hooks/hooks.json + GEMINI.md | gemini extensions install <out>/<id> --consent (driven end-to-end by `install --method marketplace --targets gemini-cli`; live-verified on Linux/gemini 0.36.0)MCP is declared INLINE in the manifest (no separate .mcp.json); commands are TOML. --consent is required non-interactively; re-install refuses (probe-first driver handles it). CAVEAT: gemini >= 0.41 (e.g. on Windows) gates a local install behind a 'trust this folder' prompt --consent doesn't cover — trust the folder once interactively, or set security.folderTrust.enabled:false; the driver degrades to an actionable warn (no hang). |
qwen-extension#5 | Qwen Code | qwen-extension.json (inline mcpServers) + commands/<n>.md + agents/, skills/, hooks/hooks.json + QWEN.md | qwen extensions install <out>/<id> (driven by `install --method marketplace --targets qwen-code`; driver shipped, pending a live host)A Gemini-CLI fork: commands are Markdown (not TOML) and the context file is QWEN.md. |
agy-plugin#6 | Antigravity CLI / IDE | plugin.json (root marker) + mcp_config.json (SEPARATE) + commands/, agents/, skills/, hooks.json (bundle ROOT) | agy plugin install <out>/<id> (validate: agy plugin validate <out>/<id>; driven by `install --method marketplace --targets antigravity[-cli]`)MCP MUST be a separate mcp_config.json — an inline mcpServers in plugin.json is NOT read. hooks.json sits at the bundle ROOT (agy 1.0.7 ignores hooks/hooks.json). No marketplace catalog ships. |
cursor-plugin#7 | Cursor | .cursor-plugin/plugin.json (pointer fields) + .cursor-plugin/marketplace.json + commands/, agents/, skills/, hooks/hooks.json, mcp.json | link <out>/<id> into ~/.cursor/plugins/local/<id>/ then Reload Window (or publish <out> as a Cursor marketplace repo)Manifest surface fields are POINTERS ("skills":"./skills/", "mcpServers":"./mcp.json"). MCP file is mcp.json (no leading dot). |
kimi-plugin#8 | Kimi CLI | kimi.plugin.json (skills pointer + inline mcpServers) + skills/<n>/SKILL.md | kimi plugin install <out>/<id>Skills + MCP ONLY. Commands, subagents, and hooks are DROPPED (Kimi ignores them) and a drop note is returned. |
npm-plugin#9 | OpenCode · Kilo (CLI + ext) · Pi | package.json (type:module, exports, keywords) + index.js (ESM bridge) + skills/<n>/SKILL.md + README.md | LOCAL (no publish): opencode/kilo plugin --global file://<out>/<id> — driven end-to-end by `install --method marketplace --targets opencode|kilo` (live-verified; writes a file:// entry into the host config plugin array, removed by editing it back). Or publish: npm publish <out>/<id> then opencode/kilo plugin install <pkg>. (pi is registry-only with no hook layer → not drivable.)A publishable npm package whose default export is a plugin fn that shells each hook to the home-bin. Commands/subagents are native host dirs and MCP is a config key, so they are NOT bundled (notes record this). |
mcp-server-json#10 | Official MCP Registry (cross-vendor discovery) | server.json (schema 2025-12-11: name = <namespace>/<id>, version, packages[]{registryType,identifier,transport} | remotes[]) | mcp-publisher login … && mcp-publisher publish (the dev runs this)OFFICIAL standard artifact. Describes the dev's REAL upstream server (NOT our serve wrapper). Opt-in: requires publish.registryNamespace (a namespace you own) + publish.packageName; excluded from --format all. |
mcpb#11 | Claude Desktop + any MCPB host (one-click local install) | manifest.json (manifest_version 0.3, self-contained node server, secrets→user_config) + README packaging recipe | vendor server/ then: npx @anthropic-ai/mcpb pack . (the dev runs this)OFFICIAL standard artifact. Emits a conformant manifest + recipe, NOT the .mcpb zip (self-contained bundling is the dev's step). Opt-in: requires publish.author.name + a stdio server; excluded from --format all. |
Telemetry carries through every bundle#
Hooks use the universal home-bin hook command and the MCP entry is serve-wrapped with --host <platform> in every bundle — exactly as the branded direct install would. So a marketplace-installed connector still reports per-tool tokens: the wrapped MCP entry routes through the one stable home binary, and the hooks shell back to the same entrypoint, keeping the telemetry serve-wrapper intact end to end.
# the default agent-plugin bundle installs from a local marketplace, two steps —
# the SAME <out> dir serves Codex and GitHub Copilot CLI (VS Code picks up the CLI install):
codex plugin marketplace add ./dist-plugin && codex plugin add acme-db@agent-connector
copilot plugin marketplace add ./dist-plugin && copilot plugin install acme-db@agent-connector
# acme-db is the package-derived connector id inside the generated bundle,
# not an extra id the user enters in defineConnector.
# a claude-plugin bundle (--format claude-plugin) is the Claude Code equivalent:
/plugin marketplace add ./dist-plugin
/plugin install acme-db@agent-connector
# the wrapped MCP entry still routes through the one agent-connector runtime —
# agent-plugin via its bundled launcher (no absolute path in the bundle):
# node ${PLUGIN_ROOT}/bin/agent-connector.mjs serve --connector acme-db -- <real cmd>
# claude-plugin via the home-bin path:
# agent-connector serve --connector acme-db --host claude-code -- <real cmd>
# so a marketplace-installed connector STILL reports per-tool tokens.Lossy formats are never silent
Some hosts can't carry every surface.kimi-plugin keeps skills + MCP only — commands, subagents, and hooks are dropped. npm-plugin bundles only the hook bridge (+ skills for Pi); commands/subagents are native host dirs and MCP is a config key, so they aren't bundled. agent-plugin keeps skills + MCP portable and carries hooks/commands/subagents per client-extension namespace — com.github.copilot/ (Copilot CLI, VS Code, JetBrains) and com.openai/ (Codex) — which other clients ignore. In every case the emitter returns explicit drop notes the CLI prints, so a lossy bundle is never silent.