Live today! Discover, install, and trust MCP servers with one click
guidesUpdated February 26, 2026

How to publish your MCP server to PyPI

A complete guide to packaging and publishing your Python MCP server to PyPI: manually or with the mcp-creator tool that does it for you.

Key takeaways

  • Use mcp-creator for an automated path, or set up manually with pyproject.toml + uv build + uv publish
  • Name your package with the -mcp suffix for discoverability on PyPI
  • Push to GitHub and submit to MCP Marketplace to get security-scanned and listed

Why publish to PyPI

You built a Python MCP server. It works on your machine. Now you want other people to use it.

PyPI (the Python Package Index) is where pip install pulls packages from. When your server is on PyPI, anyone can install it with a single command:

pip install your-server-name

No cloning repos. No manual setup. One command and it works. This is the standard way to distribute Python MCP servers, and it is what MCP Marketplace expects when generating install instructions for your users.

This guide covers Python servers distributed via PyPI (pip install). Publishing a TypeScript server to npm? See How to build an MCP server or use mcp-creator-typescript for the automated path. There is also a third option: remote hosted servers where users connect to a URL and nothing is installed locally.

Not sure how to build the server itself? Start with How to build an MCP server first, then return here to publish it.

Two paths: automated or manual

There are two ways to go from idea to published MCP server:

  1. Automated with mcp-creator-python: install one tool, tell your AI assistant what you want to build, and it handles the scaffolding, building, and publishing for you. Good for speed and for people new to Python packaging.
  2. Manual: you set up the project structure, write the config files, build, and publish yourself. Full control, good for learning.

Both paths produce the same result: a properly structured Python MCP server on PyPI that anyone can install.

Path A: Use mcp-creator-python (recommended for beginners)

mcp-creator-python is an MCP server that helps you create other MCP servers. Install it, add it to your AI assistant, and describe what you want to build in plain English.

pip install mcp-creator-python
Terminal
claude mcp add mcp-creator-python -- mcp-creator-python

Then just tell your AI what to build:

"I want an MCP server that checks the weather for any city"

It handles everything: checks the PyPI name, scaffolds the project, builds, publishes to PyPI, creates a GitHub repo, and generates a marketplace submission checklist. You fill in your real logic in the services/ folder.

See the full MCP Creator guide for a detailed walkthrough.

Path B: Manual setup

If you prefer full control or want to understand what's happening under the hood, here is the step-by-step manual process.

What you need

This guide uses uv because it handles building and publishing in two commands. If you prefer pip and twine, the concepts are identical.

Step 1: Structure your project

PyPI packages need a specific layout. Here is the standard structure for a Python MCP server:

my-mcp-server/
├── pyproject.toml          # Package metadata and dependencies
├── README.md               # What users see on PyPI
├── .gitignore
├── src/
│   └── my_mcp_server/      # Your Python module (underscores, not hyphens)
│       ├── __init__.py
│       ├── server.py        # MCP server definition and entry point
│       ├── tools/           # Tool implementations
│       │   ├── __init__.py
│       │   └── my_tool.py
│       └── services/        # Business logic, API clients
│           ├── __init__.py
│           └── my_service.py
└── tests/
    └── test_my_tool.py

Two things to note:

  1. Source code goes in src/<module_name>/. This is called the "src layout" and it prevents import issues during development.
  2. The module name uses underscores (my_mcp_server), even if the package name uses hyphens (my-mcp-server). Python does not allow hyphens in import names.

Step 2: Configure pyproject.toml

This is the single file that tells PyPI everything about your package. Here is a working example:

[project]
name = "my-mcp-server"
version = "0.1.0"
description = "One-line description of what your server does"
readme = "README.md"
requires-python = ">=3.11"
license = { text = "MIT" }
dependencies = [
    "mcp[cli]>=1.0.0",
    # Add your other dependencies here
]

[project.scripts]
my-mcp-server = "my_mcp_server.server:main"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/my_mcp_server"]

The key sections:

  • name: What users type after pip install. Use hyphens for readability.
  • version: Start at 0.1.0. Bump it every time you publish an update.
  • dependencies: Everything your server needs to run. The mcp[cli] package is required for all MCP servers.
  • [project.scripts]: This creates the CLI command. After installing, users can run my-mcp-server directly from their terminal.
  • [tool.hatch.build.targets.wheel]: Points to your source code directory.

Step 3: Create a PyPI account and API token

  1. Go to pypi.org/account/register and create a free account.
  2. After signing in, go to Account settings and scroll to API tokens.
  3. Click Add API token. Name it anything (e.g., "MCP servers"). Set the scope to Entire account for your first publish. You can create project-scoped tokens later.
  4. Copy the token. It starts with pypi- and you will only see it once.

Store the token so uv publish can use it. Add this line to your shell profile:

macOS / Linux (zsh):

echo 'export UV_PUBLISH_TOKEN="pypi-your-token-here"' >> ~/.zshrc
source ~/.zshrc

macOS / Linux (bash):

echo 'export UV_PUBLISH_TOKEN="pypi-your-token-here"' >> ~/.bashrc
source ~/.bashrc

This persists across terminal sessions. You only need to do this once.

Step 4: Build your package

From your project root:

uv build

This creates two files in dist/:

dist/
├── my_mcp_server-0.1.0.tar.gz      # Source distribution
└── my_mcp_server-0.1.0-py3-none-any.whl  # Wheel (what pip installs)

If the build fails, check that your pyproject.toml paths match your actual directory structure.

Step 5: Publish to PyPI

uv publish

That is it. Your package is now live on PyPI. Anyone in the world can install it:

pip install my-mcp-server

Visit https://pypi.org/project/my-mcp-server/ to see your listing.

Step 6: Push to GitHub

MCP Marketplace requires a repository URL when you submit your server: submitted servers go through an automated security scan before being listed. Create a GitHub repo and push your code:

git init
git add .
git commit -m "Initial commit"
gh repo create my-mcp-server --public --source . --push --description "Description of your MCP server"

This uses the GitHub CLI. If you don't have it, install it with brew install gh (macOS) and run gh auth login to authenticate.

Step 7: Tell users how to use it

Your README should include the MCP config snippet so users know exactly how to add your server to their AI assistant:

{
  "mcpServers": {
    "my-mcp-server": {
      "command": "my-mcp-server"
    }
  }
}

If your server requires environment variables (API keys, tokens), include those too:

{
  "mcpServers": {
    "my-mcp-server": {
      "command": "my-mcp-server",
      "env": {
        "MY_API_KEY": "your-key-here"
      }
    }
  }
}

Publishing updates

When you make changes:

  1. Bump the version in pyproject.toml (e.g., 0.1.0 to 0.1.1)
  2. Run uv build again
  3. Run uv publish

PyPI does not allow overwriting an existing version. You must bump the version number every time.

Package naming tips

PyPI has strict naming rules. A few things to know:

  • Name collisions: PyPI will reject your package if the name is too similar to an existing one. Check pypi.org first: or use mcp-creator-python's check_pypi_name tool.
  • Use the -mcp suffix: Names like weather-mcp or finance-mcp are clear, descriptive, and unlikely to collide. This also makes your package discoverable when people search PyPI for MCP servers.
  • Hyphens vs underscores: Use hyphens in the package name (my-mcp-server) and underscores in the module name (my_mcp_server). Python normalizes them, but hyphens are the convention for PyPI.

Common issues

"The name is too similar to an existing project": Pick a more specific name. Adding -mcp as a suffix usually resolves this.

"403 Forbidden" on publish: Your API token is missing or expired. Check that UV_PUBLISH_TOKEN is set in your shell (echo $UV_PUBLISH_TOKEN). If empty, re-add it to your shell profile and run source ~/.zshrc.

"File already exists" on publish: You are trying to upload the same version twice. Bump the version in pyproject.toml, rebuild, and publish again.

Build fails with "package not found": Make sure the packages path in pyproject.toml matches your actual directory. If your code is at src/my_mcp_server/, the config should be packages = ["src/my_mcp_server"].

Submit to MCP Marketplace

Once your package is on PyPI and your code is on GitHub, submit it to MCP Marketplace to get it listed, security-scanned, and discoverable. You will need your PyPI package name and GitHub repository URL for the submission.

Browse MCP Marketplace to see what other creators have built.

Want to charge for your server? Read How to monetize your MCP server.

Browse MCP servers

Find the servers mentioned in this post and thousands more on MCP Marketplace. Security-checked, one-click install.

Browse servers

Keep reading