Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 42 additions & 5 deletions .github/workflows/publish-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,21 @@ on:
workflow_dispatch:
inputs:
package:
description: 'Package to publish (code-assistant, runtime, or both)'
description: 'Package to publish'
required: true
default: 'both'
default: 'all'
type: choice
options:
- both
- all
- meta-package
- code-assistant
- runtime

jobs:
publish-code-assistant:
if: |
(github.event_name == 'release' && contains(github.ref, 'code-assistant')) ||
(github.event_name == 'workflow_dispatch' && (github.event.inputs.package == 'both' || github.event.inputs.package == 'code-assistant'))
(github.event_name == 'workflow_dispatch' && (github.event.inputs.package == 'all' || github.event.inputs.package == 'code-assistant'))
runs-on: ubuntu-latest
permissions:
id-token: write # Required for trusted publishing
Expand Down Expand Up @@ -50,7 +51,7 @@ jobs:
publish-runtime:
if: |
(github.event_name == 'release' && contains(github.ref, 'runtime')) ||
(github.event_name == 'workflow_dispatch' && (github.event.inputs.package == 'both' || github.event.inputs.package == 'runtime'))
(github.event_name == 'workflow_dispatch' && (github.event.inputs.package == 'all' || github.event.inputs.package == 'runtime'))
runs-on: ubuntu-latest
permissions:
id-token: write # Required for trusted publishing
Expand All @@ -77,3 +78,39 @@ jobs:
with:
packages-dir: qiskit-ibm-runtime-mcp-server/dist/
verbose: true

publish-meta-package:
runs-on: ubuntu-latest
# Meta-package should be published after individual servers
needs: [publish-code-assistant, publish-runtime]
# Allow meta-package to run even if individual packages were skipped (already published)
if: |
always() &&
(needs.publish-code-assistant.result == 'success' || needs.publish-code-assistant.result == 'skipped') &&
(needs.publish-runtime.result == 'success' || needs.publish-runtime.result == 'skipped') &&
((github.event_name == 'release' && contains(github.ref, 'meta')) ||
(github.event_name == 'workflow_dispatch' && (github.event.inputs.package == 'all' || github.event.inputs.package == 'meta-package')))
permissions:
id-token: write # Required for trusted publishing
contents: read

steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v3
with:
version: "latest"

- name: Set up Python
run: uv python install 3.12

- name: Build meta-package
run: |
uv build

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist/
verbose: true
125 changes: 106 additions & 19 deletions PUBLISHING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,24 @@ This guide covers how to publish the Qiskit MCP servers to PyPI, both manually a

## Packages

This repository contains two separate PyPI packages:
This repository contains multiple PyPI packages:

1. **qiskit-code-assistant-mcp-server** - MCP server for Qiskit Code Assistant
2. **qiskit-ibm-runtime-mcp-server** - MCP server for IBM Quantum Runtime
3. **qiskit-mcp-servers** - Meta-package that installs all MCP servers

### Meta-Package

The `qiskit-mcp-servers` meta-package provides a convenient way to install all servers at once:

```bash
# Install all MCP servers
pip install qiskit-mcp-servers

# Or install individual servers via extras
pip install qiskit-mcp-servers[code-assistant] # Only Code Assistant
pip install qiskit-mcp-servers[runtime] # Only Runtime
```

## Automated Publishing (Recommended)

Expand Down Expand Up @@ -40,60 +54,119 @@ Alternatively, you can create releases manually through the GitHub web interface
1. Go to PyPI and create the project (if it doesn't exist):
- For `qiskit-code-assistant-mcp-server`: https://pypi.org/manage/project/qiskit-code-assistant-mcp-server/settings/publishing/
- For `qiskit-ibm-runtime-mcp-server`: https://pypi.org/manage/project/qiskit-ibm-runtime-mcp-server/settings/publishing/
- For `qiskit-mcp-servers`: https://pypi.org/manage/project/qiskit-mcp-servers/settings/publishing/

2. Add a "trusted publisher" with these settings:
- **PyPI Project Name**: `qiskit-code-assistant-mcp-server` (or `qiskit-ibm-runtime-mcp-server`)
- **PyPI Project Name**: `qiskit-code-assistant-mcp-server` (or `qiskit-ibm-runtime-mcp-server` or `qiskit-mcp-servers`)
- **Owner**: `AI4quantum`
- **Repository**: `qiskit-mcp-servers`
- **Repository**: `mcp-servers`
- **Workflow name**: `publish-pypi.yml`
- **Environment name**: (leave blank)

### Publishing via GitHub Releases

The workflow automatically publishes when you create a GitHub release:
The workflow automatically publishes when you create a GitHub release. The tag name determines which package is published.

#### Tag Naming Convention

| Tag Pattern | Package Published |
|-------------|-------------------|
| `code-assistant-v*` | qiskit-code-assistant-mcp-server |
| `runtime-v*` | qiskit-ibm-runtime-mcp-server |
| `meta-v*` | qiskit-mcp-servers (meta-package) |

#### Complete Release Workflow

Follow these steps to release a package:

##### Step 1: Update Version

Edit the version in the appropriate `pyproject.toml`:
- **Code Assistant**: `qiskit-code-assistant-mcp-server/pyproject.toml`
- **Runtime**: `qiskit-ibm-runtime-mcp-server/pyproject.toml`
- **Meta-package**: `pyproject.toml` (root)

##### Step 2: Commit and Push Changes

```bash
# Stage and commit the version change
git add -A
git commit -m "Bump qiskit-code-assistant-mcp-server to v0.1.1"

# Push to main branch
git push origin main
```

##### Step 3: Create and Push Tag

#### For Code Assistant Server:
```bash
# Update version in qiskit-code-assistant-mcp-server/pyproject.toml
# Then create and push a tag
# Create an annotated tag
git tag -a code-assistant-v0.1.1 -m "Release qiskit-code-assistant-mcp-server v0.1.1"

# Push the tag to GitHub
git push origin code-assistant-v0.1.1
```

##### Step 4: Create GitHub Release

```bash
# Create the release (this triggers the publish workflow)
gh release create code-assistant-v0.1.1 \
--title "qiskit-code-assistant-mcp-server v0.1.1" \
--generate-notes
```

Or use `--notes "Your release notes here"` instead of `--generate-notes` for custom notes.

#### Quick Reference Examples

# Create a GitHub release from this tag
gh release create code-assistant-v0.1.1 --title "qiskit-code-assistant-mcp-server v0.1.1" --notes "Release notes here"
**Code Assistant Server:**
```bash
# After updating version in qiskit-code-assistant-mcp-server/pyproject.toml
git add -A && git commit -m "Bump code-assistant to v0.1.1" && git push origin main
git tag -a code-assistant-v0.1.1 -m "Release v0.1.1" && git push origin code-assistant-v0.1.1
gh release create code-assistant-v0.1.1 --title "qiskit-code-assistant-mcp-server v0.1.1" --generate-notes
```

#### For Runtime Server:
**Runtime Server:**
```bash
# Update version in qiskit-ibm-runtime-mcp-server/pyproject.toml
# Then create and push a tag
git tag -a runtime-v0.1.1 -m "Release qiskit-ibm-runtime-mcp-server v0.1.1"
git push origin runtime-v0.1.1
# After updating version in qiskit-ibm-runtime-mcp-server/pyproject.toml
git add -A && git commit -m "Bump runtime to v0.1.1" && git push origin main
git tag -a runtime-v0.1.1 -m "Release v0.1.1" && git push origin runtime-v0.1.1
gh release create runtime-v0.1.1 --title "qiskit-ibm-runtime-mcp-server v0.1.1" --generate-notes
```

# Create a GitHub release from this tag
gh release create runtime-v0.1.1 --title "qiskit-ibm-runtime-mcp-server v0.1.1" --notes "Release notes here"
**Meta-Package:**
```bash
# After updating version in pyproject.toml (root)
git add -A && git commit -m "Bump meta-package to v0.1.1" && git push origin main
git tag -a meta-v0.1.1 -m "Release v0.1.1" && git push origin meta-v0.1.1
gh release create meta-v0.1.1 --title "qiskit-mcp-servers v0.1.1" --generate-notes
```

### Manual Workflow Trigger

You can also trigger publishing manually via GitHub Actions using the CLI:

```bash
# Publish both packages
gh workflow run "Publish to PyPI" -f package=both
# Publish all packages (individual servers + meta-package)
gh workflow run "Publish to PyPI" -f package=all

# Publish only code-assistant
gh workflow run "Publish to PyPI" -f package=code-assistant

# Publish only runtime
gh workflow run "Publish to PyPI" -f package=runtime

# Publish only meta-package
gh workflow run "Publish to PyPI" -f package=meta-package
```

Alternatively, you can trigger via the GitHub web interface:

1. Go to **Actions** → **Publish to PyPI**
2. Click **Run workflow**
3. Select which package to publish: `both`, `code-assistant`, or `runtime`
3. Select which package to publish: `all`, `meta-package`, `code-assistant`, or `runtime`

## Manual Publishing

Expand All @@ -118,6 +191,7 @@ pip install uv
Edit the version in `pyproject.toml`:
- **Code Assistant**: `qiskit-code-assistant-mcp-server/pyproject.toml`
- **Runtime**: `qiskit-ibm-runtime-mcp-server/pyproject.toml`
- **Meta-package**: `pyproject.toml` (root)

#### 2. Build the Package

Expand All @@ -143,6 +217,15 @@ uv build
python -m build
```

**For Meta-Package:**
```bash
# From repository root
uv build

# Or with build
python -m build
```

This creates `.whl` and `.tar.gz` files in the `dist/` directory.

#### 3. Verify the Build
Expand Down Expand Up @@ -188,6 +271,9 @@ pip install qiskit-code-assistant-mcp-server

# For Runtime
pip install qiskit-ibm-runtime-mcp-server

# For Meta-Package (installs all servers)
pip install qiskit-mcp-servers
```

## Version Management
Expand All @@ -206,6 +292,7 @@ The current version for each package is defined in their respective `pyproject.t

- **qiskit-code-assistant-mcp-server**: See [qiskit-code-assistant-mcp-server/pyproject.toml](qiskit-code-assistant-mcp-server/pyproject.toml) (search for `version =`)
- **qiskit-ibm-runtime-mcp-server**: See [qiskit-ibm-runtime-mcp-server/pyproject.toml](qiskit-ibm-runtime-mcp-server/pyproject.toml) (search for `version =`)
- **qiskit-mcp-servers**: See [pyproject.toml](pyproject.toml) (search for `version =`)

## Pre-Publication Checklist

Expand Down
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,20 @@ Comprehensive interface to IBM Quantum hardware via Qiskit IBM Runtime
- **IBM Quantum account** and API token
- **Qiskit Code Assistant access** (for code assistant server)

### Installation & Usage
### Installation

#### Install from PyPI

```bash
# Install all MCP servers at once
pip install qiskit-mcp-servers

# Or install individual servers
pip install qiskit-code-assistant-mcp-server
pip install qiskit-ibm-runtime-mcp-server
```

#### Install from Source

Each server is designed to run independently. Choose the server you need:

Expand All @@ -55,7 +68,7 @@ cd qiskit-code-assistant-mcp-server
uv run qiskit-code-assistant-mcp-server
```

#### ⚙️ IBM Runtime Server
#### ⚙️ IBM Runtime Server
```bash
cd qiskit-ibm-runtime-mcp-server
uv run qiskit-ibm-runtime-mcp-server
Expand Down
28 changes: 24 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "qiskit-mcp-servers"
version = "0.1.0"
description = "Model Context Protocol servers for IBM Quantum services and Qiskit"
readme = "README.md"
requires-python = ">=3.10"
requires-python = ">=3.10,<3.15"
license = {text = "Apache-2.0"}
authors = [
{name = "Quantum+AI Team. IBM Quantum", email = "[email protected]"}
Expand All @@ -23,6 +23,22 @@ classifiers = [
"Topic :: Software Development :: Libraries :: Python Modules",
]

# Meta-package dependencies: installs all MCP servers
dependencies = [
"qiskit-code-assistant-mcp-server>=0.1.0",
"qiskit-ibm-runtime-mcp-server>=0.1.0",
]

[project.optional-dependencies]
# Install individual servers
code-assistant = ["qiskit-code-assistant-mcp-server>=0.1.0"]
runtime = ["qiskit-ibm-runtime-mcp-server>=0.1.0"]
# Install all servers (same as default dependencies)
all = [
"qiskit-code-assistant-mcp-server>=0.1.0",
"qiskit-ibm-runtime-mcp-server>=0.1.0",
]

[project.urls]
Homepage = "https://github.com/Qiskit/mcp-servers"
Repository = "https://github.com/Qiskit/mcp-servers"
Expand All @@ -33,17 +49,21 @@ Documentation = "https://github.com/Qiskit/mcp-servers#readme"
requires = ["hatchling"]
build-backend = "hatchling.build"

# This is a workspace root, not an installable package
[tool.hatch.build.targets.wheel]
only-include = ["nonexistent_dummy_path"]
packages = ["src/qiskit_mcp_servers"]

# Workspace configuration for monorepo
[tool.uv.workspace]
members = [
"qiskit-code-assistant-mcp-server",
"qiskit-ibm-runtime-mcp-server"
"qiskit-ibm-runtime-mcp-server",
]

# Source configuration for workspace dependencies
[tool.uv.sources]
qiskit-code-assistant-mcp-server = { workspace = true }
qiskit-ibm-runtime-mcp-server = { workspace = true }

# Shared tool configurations
[tool.ruff]
# Extend the shared ruff.toml configuration
Expand Down
16 changes: 16 additions & 0 deletions src/qiskit_mcp_servers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
Qiskit MCP Servers - Meta-package for all Qiskit MCP servers.

This is a meta-package that installs all available Qiskit MCP servers:
- qiskit-code-assistant-mcp-server: MCP server for Qiskit Code Assistant
- qiskit-ibm-runtime-mcp-server: MCP server for IBM Quantum Runtime

Usage:
pip install qiskit-mcp-servers

To install individual servers:
pip install qiskit-mcp-servers[code-assistant]
pip install qiskit-mcp-servers[runtime]
"""

__version__ = "0.1.0"
Loading