Publishing & Distribution Guide¶
This document describes every channel through which imgflip-mcp is (or can
be) distributed, what each one requires, and how a release works end to end.
Overview¶
| Channel | Audience | Artifact | How it gets there |
|---|---|---|---|
| npm | everyone (npx -y imgflip-mcp) |
npm package | npm publish (automated by CI) |
| MCP Registry | all MCP clients | server.json metadata |
mcp-publisher (automated by CI) |
| GitHub MCP Registry | Copilot / VS Code users | — | fed automatically from the MCP Registry |
| Claude Desktop extension directory | Claude Desktop users | .mcpb bundle |
built by CI, submitted manually once |
| Claude Code plugin marketplace | Claude Code users | this repo itself | nothing to publish — the repo is the marketplace |
| Community directories (Smithery, Glama, mcp.so, PulseMCP) | discovery | — | mostly indexed automatically |
The repo already contains all required metadata files:
package.json npm package + "mcpName" ownership proof for the MCP Registry
server.json MCP Registry entry (registry metadata, env var docs)
manifest.json Claude Desktop Extension (MCPB) manifest with user_config
.mcpbignore what to exclude from the .mcpb bundle
.claude-plugin/ Claude Code plugin + marketplace definition
.mcp.json MCP server definition used by the Claude Code plugin
PRIVACY.md privacy policy (required for the Claude extension directory)
.github/workflows/publish.yml the automated release pipeline
One-time setup¶
- npm account — create/log into an npm account that may publish the
imgflip-mcppackage name, generate an automation access token, and add it to the GitHub repo as theNPM_TOKENactions secret (Settings → Secrets and variables → Actions). - Nothing else — the MCP Registry step authenticates via GitHub OIDC (the
io.github.mariokernich/*namespace is proven by the workflow running in this repo), and the GitHub release is created with the built-inGITHUB_TOKEN.
Cutting a release¶
- Bump the version — one command updates
package.jsonand syncs it toserver.json,manifest.jsonand.claude-plugin/*(via thescripts/sync-versions.mjshook), commits, and creates the tag:
- Push with the tag:
- The
Publishworkflow then: - verifies the version consistency,
- builds and publishes the npm package (with provenance),
- publishes
server.jsonto the MCP Registry, - packs the Desktop Extension and attaches
imgflip-mcp-v1.0.1.mcpbto a GitHub release.
Everything below documents what each channel is and the manual steps, in case you ever need to run them by hand.
1. npm¶
The MCP Registry stores metadata only — the actual code must live on npm.
The published package contains dist/ plus a bin entry, so consumers run
it with npx -y imgflip-mcp and never need to clone this repo.
Manual publish:
(npm publish also works in this pnpm repo — publishing only packs dist/
per the files field and needs no node_modules layout knowledge.)
The mcpName field in package.json
(io.github.mariokernich/imgflip-mcp) is how the MCP Registry verifies that
the npm package and the registry entry belong together — don't remove it.
2. Official MCP Registry (→ Copilot, VS Code, Claude Code)¶
The MCP Registry is the shared,
open catalog that downstream clients consume — most importantly the
GitHub MCP Registry that Copilot and VS Code use
for MCP server discovery, and Claude Code's /mcp ecosystem. Publishing
here once makes the server discoverable in all of them; there is no separate
"Copilot marketplace" submission.
The entry is described by server.json. The namespace
io.github.mariokernich/* is authenticated via GitHub (interactive device
login locally, OIDC in CI).
Manual publish:
# install the publisher CLI (or: brew install mcp-publisher)
# note: release assets use amd64/arm64, not uname's x86_64/aarch64
ARCH=$(uname -m); case "$ARCH" in x86_64) ARCH=amd64 ;; aarch64) ARCH=arm64 ;; esac
curl -fsSL "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_${ARCH}.tar.gz" | tar xz mcp-publisher
./mcp-publisher login github # opens a device-code login
./mcp-publisher publish # validates and uploads server.json
Verify afterwards:
curl -s "https://registry.modelcontextprotocol.io/v0/servers?search=io.github.mariokernich/imgflip-mcp"
3. Claude Desktop extension directory (.mcpb)¶
Claude Desktop installs local MCP servers as one-click Desktop Extensions
(.mcpb bundles — a zip of manifest.json, dist/ and production
node_modules). Our manifest.json declares the
credentials as user_config, so Claude Desktop shows a friendly form
(username, password, premium checkbox) at install time and stores the
password in the OS keychain — users never touch JSON.
Build locally:
pnpm install --frozen-lockfile && pnpm build
# hoisted layout = flat, symlink-free node_modules for a portable bundle
rm -rf node_modules
pnpm install --prod --frozen-lockfile --config.node-linker=hoisted
pnpm dlx @anthropic-ai/mcpb pack . imgflip-mcp.mcpb
Test it by double-clicking the file (or Settings → Extensions → Install extension…) in Claude Desktop.
Distribution options:
- GitHub release — the CI pipeline attaches the
.mcpbto every release; anyone can download and double-click it. Works today, no review needed. - Official extension directory — submit the extension through Anthropic's
submission process (see the
connectors/extension submission docs
and the
Desktop Extensions announcement).
Requirements already covered by this repo: MIT license, privacy policy
(
PRIVACY.md+privacy_policiesin the manifest + the Privacy section in the README),user_configfor secrets, and no bundled credentials.
Note: the claude.ai Connectors directory (web) only lists remote MCP servers (hosted, OAuth). This server is local/stdio by design — the desktop extension directory is the right Claude channel for it.
4. Claude Code plugin marketplace¶
Claude Code marketplaces are decentralized: any repo containing
.claude-plugin/marketplace.json is a marketplace. This repo doubles as
one, with the plugin defined by .claude-plugin/plugin.json and the MCP
server wiring in .mcp.json.
Users install it with:
The plugin starts the server via npx -y imgflip-mcp and passes through the
IMGFLIP_USERNAME / IMGFLIP_PASSWORD / IMGFLIP_PREMIUM environment
variables, so users just export those in their shell profile.
To get listed in community-curated marketplace collections, submit the repo to lists like claudecodemarketplace.com or awesome-claude-plugins style repos — but the self-hosted marketplace above works without any approval.
5. VS Code / GitHub Copilot¶
Once the server is in the MCP Registry it appears in the GitHub MCP Registry
and VS Code's MCP server browsing (Extensions view → MCP SERVERS,
@mcp search). Independent of that, the README contains an
Install in VS Code badge that deep-links VS Code's vscode:mcp/install
handler with the full server config (including secure prompts for the
credentials).
To regenerate the badge URL after config changes:
python3 - <<'EOF'
import json, urllib.parse
cfg = {
"name": "imgflip",
"command": "npx",
"args": ["-y", "imgflip-mcp"],
"env": {
"IMGFLIP_USERNAME": "${input:imgflip_username}",
"IMGFLIP_PASSWORD": "${input:imgflip_password}"
},
"inputs": [
{"id": "imgflip_username", "type": "promptString", "description": "Imgflip username"},
{"id": "imgflip_password", "type": "promptString", "description": "Imgflip password", "password": True}
]
}
uri = "vscode:mcp/install?" + json.dumps(cfg, separators=(",", ":"))
print("https://insiders.vscode.dev/redirect?url=" + urllib.parse.quote(uri, safe=""))
EOF
CLI alternative for users:
code --add-mcp '{"name":"imgflip","command":"npx","args":["-y","imgflip-mcp"],"env":{"IMGFLIP_USERNAME":"${input:imgflip_username}","IMGFLIP_PASSWORD":"${input:imgflip_password}"},"inputs":[{"id":"imgflip_username","type":"promptString","description":"Imgflip username"},{"id":"imgflip_password","type":"promptString","description":"Imgflip password","password":true}]}'
6. Community directories¶
These significantly boost discovery and mostly index automatically once the npm package and MCP Registry entry exist:
- Smithery — claim/submit the server with your GitHub login
- Glama — indexes GitHub automatically; claiming improves the listing
- mcp.so — submit via their form/GitHub issue
- PulseMCP — indexes the MCP Registry
Release checklist (TL;DR)¶
- [ ]
NPM_TOKENsecret exists (one-time) - [ ]
CHANGELOG.md: move[Unreleased]entries under the new version - [ ]
pnpm lint && pnpm testgreen - [ ]
npm version patch|minor|major(bumps + syncs all version fields + tags) - [ ]
git push origin main --follow-tags→ CI publishes npm + MCP Registry +.mcpbrelease - [ ] (first release only) submit the
.mcpbto the Claude extension directory - [ ] (optional) claim listings on Smithery/Glama