Plugin developer guide

Turn an MCP Registry server.json into a Claude Code plugin

By HOL · Reviewed by Michael Kantor on

Direct answer

If your MCP server already has a server.json for the MCP Registry, hol-guard plugin package --runtimes claude-code writes a Claude Code plugin from it: .claude-plugin/plugin.json with the name, version, description and repository, and .mcp.json with the launch command. An npm package runs with npx, a PyPI package with uvx, and an OCI image with docker run. The same run can write Codex, Cursor, VS Code, Gemini CLI and OpenCode configs.

Who this is for

MCP server authors who publish to the MCP Registry and want one-step installs in agent runtimes.

Good fit

  • An npm, PyPI or OCI MCP server already described in server.json
  • A remote MCP server that wants a Claude Code plugin pointing at its URL
  • A maintainer adding per-runtime install snippets to a README

Not a fit

  • Servers with several packages in one server.json; the Kit uses the first package
  • Servers that need runtime-specific flags the Registry schema cannot describe

Steps

  1. 1.Install HOL Guard

    The Plugin Kit ships inside HOL Guard 3.57 and newer. It needs Python 3.10 or newer and pipx. If Guard is already installed, upgrade it, then check that hol-guard --version reports 3.57 or newer.

    pipx install hol-guard
    pipx upgrade hol-guard
    hol-guard --version
  2. 2.Check server.json

    The check reads server.json, turns its first package into an MCP server entry and reports gaps such as a missing license. Environment variables listed in the package become references the user fills in.

    hol-guard plugin check .
  3. 3.Write the Claude Code plugin

    The output holds .claude-plugin/plugin.json and .mcp.json. For an npm package such as @acme/notes-mcp at 2.0.1, the launch command is npx -y @acme/[email protected], and a secret such as NOTES_TOKEN is written as ${NOTES_TOKEN}.

    hol-guard plugin package . --runtimes claude-code --out dist/hol-plugin
  4. 4.Add the other runtimes

    Leave out --runtimes to write every runtime that can load an MCP server. Each config uses that runtime's environment-variable syntax.

    hol-guard plugin package . --out dist/hol-plugin --force
  5. 5.Validate the plugin

    Load the Claude Code output with Claude Code's own validator before you add it to a marketplace.

    claude plugin validate dist/hol-plugin/claude-code
  6. 6.Connect the repository on HOL

    Open the connect page with your repository to verify ownership and claim the listing. hol-guard plugin links prints the same link with your repository filled in. Installing the Guard GitHub App on the repository verifies its listings automatically.

    hol-guard plugin links .

How a server.json package becomes a launch command

Source or runtimeOutputCarriesDrops
npm packagenpx -y <identifier>@<version>Environment variable namesNothing
PyPI packageuvx <identifier>==<version>Environment variable namesNothing
OCI imagedocker run -i --rm <identifier>Environment variable namesNothing
Remote serverThe remote URLURLNothing

Limitations

  • Only the first package or remote in server.json is used.
  • The Kit does not publish to the MCP Registry or to any marketplace. It writes files you commit or attach to a release.
  • A listing or a passing check is not a safety guarantee.

Questions

Do I still need server.json if I ship a Claude Code plugin?

Keep it. The MCP Registry reads server.json, and the Kit copies your own server.json into its mcp-registry output instead of generating one.

What happens to secret environment variables?

Only the variable names are written, as references such as ${NOTES_TOKEN}. The check warns when a config ships a literal value for a variable whose name looks secret.

Can the Kit go the other way, from a plugin to server.json?

For a plugin with a single remote MCP server on GitHub, yes: the mcp-registry output is a generated server.json with a streamable HTTP remote. Package-based servers need a package identity the Kit cannot infer.

Sources

List it on HOL

Connect the repository to verify ownership and claim the listing. New plugins can be submitted for free.