Skip to main content
This guide covers the process of publishing MCP server packages to PyPI, both for testing and production releases.

Prerequisites

Before publishing:
  1. PyPI Account: Create accounts on:
  2. API Tokens: Generate API tokens:
  3. Token Storage: Save tokens securely in files (never commit these!):
    # Save Test PyPI token
    echo "pypi-your-test-token-here" > ~/.testpypi-token
    chmod 600 ~/.testpypi-token
    
    # Save PyPI token
    echo "pypi-your-production-token-here" > ~/.pypi-token
    chmod 600 ~/.pypi-token
    
Never commit API tokens to version control! Add token files to .gitignore.

Building Packages

Before publishing, build all packages:
make build
This command:
  1. Iterates through all server directories in src/
  2. Reads version information from pyproject.toml
  3. Updates __init__.py with project name and version
  4. Runs uv build to create distribution packages
  5. Creates .whl and .tar.gz files in each server’s dist/ directory

Building a Specific Server

To build only one server:
SUBDIRS=src/my-service-mcp-server make build

What Gets Built

For each server, the build process creates:
  • Wheel file: oracle.my_service_mcp_server-1.0.0-py3-none-any.whl
  • Source distribution: oracle.my_service_mcp_server-1.0.0.tar.gz
These files are placed in the server’s dist/ directory.

Publishing to Test PyPI

Why Test PyPI?

Always test your packages on Test PyPI before publishing to production. This allows you to:
  • Verify package metadata
  • Test installation process
  • Catch errors without polluting the production registry
  • Validate version numbers

Publish to Test PyPI

UV_PUBLISH_TOKEN=$(cat ~/.testpypi-token) make test-publish
This command:
  1. Reads your Test PyPI token from the file
  2. Publishes all built packages to https://test.pypi.org/legacy/
  3. Validates packages against https://test.pypi.org/simple/

Publish a Specific Server to Test PyPI

SUBDIRS=src/my-service-mcp-server UV_PUBLISH_TOKEN=$(cat ~/.testpypi-token) make test-publish

Verifying Test Packages

After publishing to Test PyPI, verify the installation:
uv run --index=https://test.pypi.org/simple oracle.my-service-mcp-server
This will:
  1. Download the package from Test PyPI
  2. Install it in a temporary environment
  3. Run the server to verify it works

Testing in an MCP Client

Configure your MCP client to use the Test PyPI version:
{
  "mcpServers": {
    "oracle-my-service-mcp-server": {
      "command": "uvx",
      "args": [
        "--index=https://test.pypi.org/simple",
        "[email protected]"
      ],
      "env": {
        "OCI_CONFIG_PROFILE": "DEFAULT",
        "FASTMCP_LOG_LEVEL": "ERROR"
      }
    }
  }
}

Publishing to Production PyPI

Only publish to production PyPI after:
  • Testing on Test PyPI
  • Verifying installation works
  • Ensuring all tests pass
  • Getting code review approval
  • Following the contribution guidelines

Publish to PyPI

UV_PUBLISH_TOKEN=$(cat ~/.pypi-token) make publish
This command:
  1. Reads your PyPI token from the file
  2. Publishes all built packages to https://upload.pypi.org/legacy/
  3. Validates packages against https://pypi.org/simple/
The UV_PUBLISH_TOKEN differs for Test PyPI and PyPI. Make sure you’re using the correct token file.

Publish a Specific Server to PyPI

SUBDIRS=src/my-service-mcp-server UV_PUBLISH_TOKEN=$(cat ~/.pypi-token) make publish

Makefile Publishing Targets

test-publish Target

test-publish:
	@set -e -o pipefail; \
	for dir in $(SUBDIRS); do \
		cd $$dir && \
		uv publish --publish-url https://test.pypi.org/legacy/ --check-url=https://test.pypi.org/simple/ && \
		cd ../..; \
	done

publish Target

publish:
	@set -e -o pipefail; \
	for dir in $(SUBDIRS); do \
		cd $$dir && \
		uv publish --check-url=https://pypi.org/simple/ && \
		cd ../..; \
	done

Version Management

Updating Version Numbers

Version numbers are defined in each server’s pyproject.toml:
[project]
name = "oracle.my-service-mcp-server"
version = "1.0.0"  # Update this before publishing

Semantic Versioning

Follow Semantic Versioning (MAJOR.MINOR.PATCH):
  • MAJOR: Incompatible API changes
  • MINOR: Add functionality (backwards-compatible)
  • PATCH: Bug fixes (backwards-compatible)

Pre-release Versions

For testing, use pre-release version numbers:
  • 1.0.0a1 - Alpha release 1
  • 1.0.0b1 - Beta release 1
  • 1.0.0rc1 - Release candidate 1

Publishing Workflow

Complete Release Process

  1. Update version in pyproject.toml
  2. Update changelog (if you maintain one)
  3. Run tests: make lint && make test
  4. Build packages: make build
  5. Test locally: Install and test the built package
  6. Publish to Test PyPI: UV_PUBLISH_TOKEN=$(cat ~/.testpypi-token) make test-publish
  7. Verify on Test PyPI: uv run --index=https://test.pypi.org/simple oracle.my-service-mcp-server
  8. Get approval: Follow contribution guidelines
  9. Publish to PyPI: UV_PUBLISH_TOKEN=$(cat ~/.pypi-token) make publish
  10. Tag release: git tag v1.0.0 && git push origin v1.0.0
  11. Announce: Update documentation and notify users

Troubleshooting

Package Already Exists

Error: File already exists Solution: You cannot overwrite a published version. Increment the version number in pyproject.toml and rebuild.

Invalid Token

Error: Invalid or non-existent authentication information Solution:
  • Verify token is correct
  • Check token hasn’t expired
  • Ensure you’re using the right token (Test PyPI vs PyPI)
  • Regenerate token if necessary

Build Files Not Found

Error: No files found to publish Solution: Run make build before attempting to publish.

Incorrect Package Name

Error: Invalid package name Solution: Verify the name field in pyproject.toml follows the correct format: oracle.service-name-mcp-server

Best Practices

  1. Always test first: Use Test PyPI before production
  2. Version carefully: Follow semantic versioning
  3. Document changes: Keep a changelog
  4. Test installations: Verify packages work after publishing
  5. Secure tokens: Never commit API tokens
  6. Review metadata: Check PyPI page after publishing
  7. Coordinate releases: Communicate with team members
  8. Tag releases: Use git tags for tracking versions

PyPI Package Pages

After publishing, your packages will be available at:
  • Test PyPI: https://test.pypi.org/project/oracle.my-service-mcp-server/
  • PyPI: https://pypi.org/project/oracle.my-service-mcp-server/
Verify that:
  • Description renders correctly
  • Links work
  • Classifiers are appropriate
  • Version number is correct
  • Author information is accurate

Installation Commands

After publishing to PyPI, users can install with:
# Latest version
uvx oracle.my-service-mcp-server@latest

# Specific version
uvx [email protected]

# From Test PyPI
uvx --index=https://test.pypi.org/simple oracle.my-service-mcp-server

Build docs developers (and LLMs) love