A server that only runs from a local dist/ path is fine for learning. Shipping means someone else can install it with npx (or pin a version) and point Cursor at it. This page is that distribution path — npm package plus the MCP Registry — not public HTTP hosting (that is Part 8).
Before you start
If Tool, stdio, or registerTool are unfamiliar, read Part 1 and Part 3 first — this post will not re-teach those basics.
Gate: apply the hardening checklist (or keep tools read-only) before you publish anything that others will run on their machines.
Bootstrap:
git clone https://github.com/SRVivek1/geekmonks-mcp-bookmarks.git
cd geekmonks-mcp-bookmarks
git checkout part-6 # or part-4 if you skipped hardening
npm install
npm run build
Companion checkpoint after packaging: tag part-7.
What “published” means here
| Layer | Where it lives | Job |
|---|---|---|
| npm package | registry.npmjs.org | The installable bits (bin → your stdio server) |
| MCP Registry | registry.modelcontextprotocol.io | Metadata so people can find the server (not a second copy of the tarball) |
The Registry is in preview and may change; treat the official quickstart as the source of truth when commands drift.
Package layout for a stdio CLI
Minimum shape (already close to the bookmarks lab):
package.json # name, version, bin, files, mcpName
dist/index.js # built entry (shebang + serveStdio)
README.md # install + Cursor snippet
server.json # MCP Registry metadata (from mcp-publisher init)
package.json fields that matter
{
"name": "@your-npm-scope/geekmonks-mcp-bookmarks",
"version": "0.7.0",
"description": "Local bookmarks MCP server (stdio)",
"type": "module",
"bin": {
"geekmonks-mcp-bookmarks": "./dist/index.js"
},
"files": [
"dist",
"README.md"
],
"engines": {
"node": ">=20"
},
"mcpName": "io.github.youruser/geekmonks-mcp-bookmarks"
}
| Field | Why |
|---|---|
bin | Lets users run the server via npx / global install |
files | Keeps the published tarball small (no src/, no tests) |
mcpName | Must match the Registry server.json name for ownership checks |
engines | Honest Node floor (20+) |
Ensure dist/index.js starts with #!/usr/bin/env node and that npm run build is part of your release habit (prepublishOnly is a common hook).
README install snippet (complete this post’s promise)
npx -y @your-npm-scope/geekmonks-mcp-bookmarks
Cursor mcp.json sketch:
{
"mcpServers": {
"bookmarks": {
"command": "npx",
"args": ["-y", "@your-npm-scope/geekmonks-mcp-bookmarks"]
}
}
}
Other hosts (Claude Desktop, etc.) use the same server binary with a different config file path — one callout, not a second tutorial.
Publish to npm
- Log in:
npm login - Build:
npm run build - Dry-run:
npm publish --access public --dry-run - Publish:
npm publish --access public
You should see: the package page on npm; npx -y @your-npm-scope/geekmonks-mcp-bookmarks starts (and waits on stdio — that is normal).
Register with the MCP Registry
Install the CLI (quickstart):
brew install mcp-publisher # or download the release binary
mcp-publisher --help
Then:
mcp-publisher init
mcp-publisher login github
# edit server.json so name === package.json mcpName, version aligns
mcp-publisher publish
Typical server.json ideas (exact schema: follow init output / package types):
{
"name": "io.github.youruser/geekmonks-mcp-bookmarks",
"description": "Local bookmarks MCP server over stdio",
"version": "0.7.0",
"packages": [
{
"registryType": "npm",
"identifier": "@your-npm-scope/geekmonks-mcp-bookmarks",
"version": "0.7.0",
"transport": {
"type": "stdio"
}
}
]
}
You should see: a Registry entry that points at your npm package; ownership verification passes because mcpName matches.
Distribution vs hosting
| Goal | Use |
|---|---|
Others run locally via npx | This post (npm + Registry) |
| Clients connect to your HTTPS URL | Part 8 |
Do not conflate “listed in the Registry” with “deployed on the internet.”
Wrap-up
You packaged a stdio MCP server for npm, proved npx, and registered metadata with mcp-publisher. Series hub: MCP Without the Hype. Safety gate: Part 6. Code checkpoint: tag part-7 on geekmonks-mcp-bookmarks.