Introduction

Building an MCP server is only half the work. To make it useful, you need to package it for distribution and document how to configure it in popular hosts like Claude Desktop, VS Code, and Cursor. A well-packaged server is one npx command away from working.

Key Concepts

  • npm publishing: Distributing your server as an npm package with a bin entry so users can run it with npx.
  • Claude Desktop configuration: The claude_desktop_config.json file that tells Claude Desktop how to launch your server.
  • Host configuration: Each MCP host (Claude Desktop, VS Code, Cursor) has its own configuration format for connecting to servers.
  • Versioning: Using semantic versioning to communicate breaking changes in your server's tool schemas.

Real World Context

You have built an MCP server that connects to your company's internal API. Your teammates want to use it with Claude Desktop and VS Code. Without proper packaging and configuration documentation, each person spends an hour figuring out how to set it up. With a published npm package and clear config examples, they are running in under a minute.

Deep Dive

Publishing to npm

To distribute your server as an npm package, add a bin entry to your package.json:

json
{
  "name": "my-mcp-server",
  "version": "1.0.0",
  "description": "An MCP server for doing useful things",
  "bin": {
    "my-mcp-server": "./dist/index.js"
  },
  "files": ["dist"],
  "scripts": {
    "build": "tsc",
    "prepublishOnly": "npm run build"
  }
}

The bin entry makes your server executable via npx my-mcp-server. The files array ensures only the compiled output is published. The prepublishOnly script guarantees the package is built before publishing.

Make sure your entry file starts with a shebang line:

typescript
#!/usr/bin/env node
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
// ... rest of your server

The shebang tells the OS to run the file with Node.js when executed directly.

Claude Desktop Configuration

Users configure Claude Desktop to launch MCP servers via claude_desktop_config.json. Here is the standard configuration for an npm-published server:

json
{
  "mcpServers": {
    "my-server": {
      "command": "npx",
      "args": ["-y", "my-mcp-server"]
    }
  }
}

The -y flag tells npx to skip the installation confirmation prompt. This configuration tells Claude Desktop to launch your server using the stdio transport whenever a conversation starts.

For servers that need environment variables, add an env field:

json
{
  "mcpServers": {
    "my-server": {
      "command": "npx",
      "args": ["-y", "my-mcp-server"],
      "env": {
        "API_KEY": "sk-abc123",
        "DATABASE_URL": "postgresql://localhost:5432/mydb"
      }
    }
  }
}

Environment variables are passed to the server process, keeping secrets out of command-line arguments.

VS Code and Cursor Configuration

VS Code and Cursor use their settings files to configure MCP servers. The format is similar to Claude Desktop:

json
{
  "mcp": {
    "servers": {
      "my-server": {
        "command": "npx",
        "args": ["-y", "my-mcp-server"]
      }
    }
  }
}

This goes in .vscode/settings.json for VS Code or the equivalent settings file for Cursor. The configuration format may vary slightly between hosts, so always check the host's documentation.

Documentation Best Practices

Your server's README should include three things: what the server does, how to install it, and configuration examples for each supported host. Here is the minimum:

markdown
## Quick Start

### Claude Desktop
Add to `claude_desktop_config.json`:
{
  "mcpServers": {
    "my-server": {
      "command": "npx",
      "args": ["-y", "my-mcp-server"]
    }
  }
}

### Available Tools
- `search`: Search the database by keyword
- `get-details`: Get details for a specific item by ID

List every tool with a brief description. Users and LLMs both benefit from knowing what tools are available before connecting.

Versioning Strategy

Use semantic versioning to communicate changes:

1.0.0 → 1.0.1  Patch: bug fix, no schema changes
1.0.0 → 1.1.0  Minor: new tool added, existing tools unchanged
1.0.0 → 2.0.0  Major: tool removed or input schema changed

Breaking changes to tool schemas deserve a major version bump because LLMs and configurations that depend on the old schema will break. Adding new tools is a minor change since existing integrations are unaffected.

Common Pitfalls

  1. Forgetting the shebang line — Without #!/usr/bin/env node at the top of your entry file, npx cannot execute it directly on Unix-like systems.
  2. Publishing source instead of compiled output — Set the files field in package.json to include only dist/. Publishing src/ adds unnecessary size and may expose source code.
  3. Not documenting environment variables — If your server needs API keys or database URLs, document every required variable and provide example values.

Best Practices

  1. Test with npx before publishing — Run npm pack and install the tarball locally to verify the package works as expected.
  2. Provide configuration examples for every host — Claude Desktop, VS Code, and Cursor all have slightly different formats. Include a copy-pasteable example for each.
  3. Use semantic versioning strictly — Breaking schema changes must be major versions. This lets users pin to a safe version range.

Summary

  • Add a bin entry to package.json and a shebang line to your entry file for npm distribution.
  • Claude Desktop uses claude_desktop_config.json with command and args fields.
  • Use the -y flag with npx to skip installation prompts.
  • Pass secrets via the env field, not command-line arguments.
  • Follow semantic versioning: new tools are minor bumps, schema changes are major bumps.

Code Examples

json
{
  "mcpServers": {
    "my-server": {
      "command": "npx",
      "args": ["-y", "my-mcp-server"]
    }
  }
}
json
{
  "name": "my-mcp-server",
  "version": "1.0.0",
  "bin": {
    "my-mcp-server": "./dist/index.js"
  },
  "files": ["dist"],
  "scripts": {
    "build": "tsc",
    "prepublishOnly": "npm run build"
  }
}
✓ Completed