This file provides guidance to AI development assistants when working with code in this repository.
Supported AI Assistants:
- IBM Bob
- Claude Code
- GitHub Copilot
- Cursor AI
- Windsurf
- Gemini CLI
- Any AI assistant with codebase context awareness
qiskit-mcp-servers is a collection of Model Context Protocol (MCP) servers that provide AI assistants, LLMs, and agents with seamless access to IBM Quantum services and Qiskit libraries for quantum computing development and research.
- Enable AI systems to interact with quantum computing resources through Qiskit
- Provide production-ready MCP servers for quantum computing workflows
- Connect AI assistants to real quantum hardware automatically
- Simplify quantum circuit execution and job management
- Provide intelligent quantum code completion and assistance
- Enable AI-powered quantum circuit optimization and transpilation
- Protocol: Model Context Protocol (MCP)
- Language: Python 3.10+ (3.11+ recommended)
- Framework: FastMCP (async-first MCP framework)
- Package Manager: uv (modern Python package manager with workspace support)
- Testing: pytest with async support, 65%+ coverage
- Code Quality: ruff (formatting + linting), mypy (type checking)
- Build System: hatchling with pyproject.toml
This is a monorepo using uv workspace containing five independent MCP servers:
qiskit-mcp-servers/
├── qiskit-mcp-server/ # Core Qiskit transpilation
├── qiskit-docs-mcp-server/ # Documentation retrieval
├── qiskit-ibm-runtime-mcp-server/ # IBM Quantum cloud services
├── qiskit-ibm-transpiler-mcp-server/ # AI-powered transpilation
├── qiskit-gym-mcp-server/ # RL-based circuit synthesis
├── .claude/skills/ # Claude Code skills
├── .github/ # GitHub templates and workflows
├── pyproject.toml # Workspace configuration & meta-package
├── mypy.ini # Shared mypy configuration
├── ruff.toml # Shared ruff configuration
├── README.md # Main repository documentation
├── PUBLISHING.md # PyPI publishing guide
├── CONTRIBUTING.md # Contribution guidelines
├── CODE_OF_CONDUCT.md # Community guidelines
└── LICENSE # Apache 2.0 license
Each server is:
- Independent: Can be installed and run separately
- Self-contained: Has its own dependencies and tests
- Publishable: Separate PyPI packages
- Consistent: Follows unified design principles
The root pyproject.toml defines a uv workspace:
[tool.uv.workspace]
members = [
"qiskit-mcp-server",
"qiskit-docs-mcp-server",
"qiskit-ibm-runtime-mcp-server",
"qiskit-ibm-transpiler-mcp-server",
"qiskit-gym-mcp-server",
]The root package is also a meta-package that installs all servers:
pip install qiskit-mcp-servers # Installs all five serversRemoved: A
qiskit-code-assistant-mcp-serverpreviously lived in this monorepo. It was removed because the underlying Qiskit Code Assistant service has been discontinued by IBM Quantum. The PyPI packageqiskit-code-assistant-mcp-serveris archived. Do not re-introduce references to it.
Each MCP server follows this standard structure:
<server-name>/
├── src/
│ └── <package_name>/
│ ├── __init__.py # Main entry point
│ ├── server.py # FastMCP server definition
│ ├── <core>.py # Core functionality (async)
│ └── utils.py # Utilities (optional)
├── tests/
│ ├── conftest.py # Test fixtures
│ ├── unit/ # Unit tests (optional subdirectory)
│ ├── integration/ # Integration tests (optional subdirectory)
│ └── test_*.py # Test files
├── examples/
│ ├── README.md # MCP server example documentation
│ ├── langchain_agent.ipynb # Interactive tutorial with step-by-step examples
│ └── langchain_agent.py # Command-line agent with multiple LLM provider support
├── pyproject.toml # Project metadata & dependencies
├── server.json # MCP Registry metadata (for publishing)
├── pytest.ini # pytest configuration (optional)
├── LICENSE # Apache 2.0 license (copy from root)
├── README.md # Server-specific documentation
├── .env.example # Environment variable template (optional)
└── run_tests.sh # Test execution script
Purpose: Core quantum circuit transpilation using Qiskit pass managers
Directory: qiskit-mcp-server/
Core Files:
server.py: FastMCP server with tool/resource definitionstranspiler.py: Qiskit transpilation functions (async)circuit_serialization.py: QASM3/QPY conversion utilitiesutils.py: Basis gate presets and coupling map topologies
Tools Provided:
| Tool | Description |
|---|---|
transpile_circuit_tool |
Transpile circuit with configurable optimization (0-3) |
analyze_circuit_tool |
Analyze circuit structure without transpiling |
compare_optimization_levels_tool |
Compare all optimization levels (0-3) |
convert_qpy_to_qasm3_tool |
Convert QPY to human-readable QASM3 |
convert_qasm3_to_qpy_tool |
Convert QASM3 to base64-encoded QPY |
load_circuit_from_qasm_tool |
Load circuit from QASM 2.0 or 3.0 string, return QPY + metadata |
export_circuit_to_qasm_tool |
Export QPY circuit to QASM 2.0 or 3.0 format |
Resources Provided:
| Resource URI | Description |
|---|---|
qiskit://transpiler/info |
Transpiler capabilities and documentation |
qiskit://transpiler/basis-gates |
Available basis gate presets |
qiskit://transpiler/topologies |
Available coupling map topologies |
Environment Variables:
QISKIT_MCP_MAX_QUBITS: Maximum allowed qubits (default: 100)QISKIT_MCP_MAX_GATES: Maximum allowed gates (default: 10000)
Purpose: Query and retrieve Qiskit documentation, guides, and API references
Directory: qiskit-docs-mcp-server/
Core Files:
server.py: FastMCP server with tool/resource definitions and lifespan managementdata_fetcher.py: Documentation fetching, search, and listing functions (async)constants.py: URL configuration, HTTP timeout settingshtml_processing.py: HTML-to-Markdown conversion for documentation pageshttp.py: Shared httpx client managementsitemap.py: Dynamic sitemap discovery (fetched at startup for module/guide/addon lists)
Tools Provided:
| Tool | Description |
|---|---|
search_docs_tool |
Search across the entire Qiskit documentation. Supports scope filters: all, documentation, api, learning, tutorials |
get_page_tool |
Fetch any Qiskit documentation page by URL (full or relative path). Supports pagination via max_length and offset |
lookup_error_code_tool |
Look up a 4-digit Qiskit/IBM Quantum error code |
Resources Provided:
| Resource URI | Description |
|---|---|
qiskit-docs://modules |
List of all Qiskit SDK modules (dynamically discovered from sitemap) |
qiskit-docs://addons |
List of all Qiskit addon packages |
qiskit-docs://guides |
List of Qiskit guides and best practices |
qiskit-docs://tutorials |
List of Qiskit tutorials |
qiskit-docs://api-packages |
List of API packages (runtime, transpiler, REST API references) |
qiskit-docs://error-codes |
List of Qiskit error code categories |
qiskit-docs://modules/{module_name} |
Fetch documentation for a specific SDK module |
qiskit-docs://guides/{guide_name} |
Fetch a specific implementation guide |
qiskit-docs://addons/{addon_name} |
Fetch documentation for a specific addon package |
Environment Variables:
QISKIT_DOCS_BASE: Base URL for Qiskit documentation (default: https://quantum.cloud.ibm.com/docs/)QISKIT_HTTP_TIMEOUT: HTTP request timeout in seconds (default: 10.0)QISKIT_SEARCH_BASE_URL: Search API base URL (default: https://quantum.cloud.ibm.com/)
Features:
- Sitemap-based dynamic discovery of modules, guides, addons, and tutorials at startup
- Generic
get_page_toolreplaces per-type tools — can fetch any page by URL - Converts HTML documentation to Markdown format
- Pagination support for large pages
- No authentication required (public documentation)
Purpose: Complete access to IBM Quantum cloud services
Directory: qiskit-ibm-runtime-mcp-server/
Core Files:
server.py: FastMCP server with tool/resource definitionsibm_runtime.py: Qiskit IBM Runtime integration (async)utils.py: Account setup and circuit format utilities
Tools Provided:
Account Management:
| Tool | Description |
|---|---|
setup_ibm_quantum_account_tool |
Configure IBM Quantum account |
delete_saved_account_tool |
Delete a saved account from disk |
list_saved_accounts_tool |
List all saved IBM Quantum accounts |
active_account_info_tool |
Get info about the currently active account |
active_instance_info_tool |
Get the active instance CRN |
available_instances_tool |
List all accessible instances |
usage_info_tool |
Get usage statistics and quota information |
Backend Discovery & Analysis:
| Tool | Description |
|---|---|
list_backends_tool |
Get available quantum backends |
least_busy_backend_tool |
Find least busy operational backend |
get_backend_properties_tool |
Get static backend properties (processor type, basis gates, qubit count) |
get_backend_calibration_tool |
Get live calibration data (T1, T2, error rates, faulty qubits) |
get_coupling_map_tool |
Get qubit connectivity (supports real and fake backends) |
find_optimal_qubit_chains_tool |
Find best linear qubit chains by calibration quality |
find_optimal_qv_qubits_tool |
Find optimal qubit subgraphs for Quantum Volume experiments |
Job Execution & Management:
| Tool | Description |
|---|---|
run_sampler_tool |
Run circuit with SamplerV2 (measurement counts). Includes dynamical decoupling and twirling |
run_estimator_tool |
Run circuit with EstimatorV2 (expectation values). Includes ZNE error mitigation |
list_my_jobs_tool |
List recent jobs |
get_job_status_tool |
Check job status |
get_job_results_tool |
Get measurement results from a completed job |
cancel_job_tool |
Cancel a running/queued job |
Resources Provided:
| Resource URI | Description |
|---|---|
ibm://status |
Service status and connection info |
circuits://bell-state |
Ready-to-run Bell state (entanglement) circuit |
circuits://ghz-state |
Ready-to-run 3-qubit GHZ state circuit |
circuits://random |
Ready-to-run quantum random number generator circuit |
circuits://superposition |
Ready-to-run single-qubit superposition circuit |
ibm://backends/{backend_name} |
Properties for a specific backend |
ibm://jobs/{job_id} |
Status of a specific job |
Environment Variables:
QISKIT_IBM_TOKEN: IBM Quantum API token (optional, can use saved credentials)QISKIT_IBM_RUNTIME_MCP_INSTANCE: IBM Quantum instance CRN (optional, speeds up startup)
Credential Resolution Priority:
- Explicit token passed to
setup_ibm_quantum_account() QISKIT_IBM_TOKENenvironment variable- Saved credentials in
~/.qiskit/qiskit-ibm.json
Purpose: AI-powered circuit transpilation with routing and synthesis
Directory: qiskit-ibm-transpiler-mcp-server/
Core Files:
server.py: FastMCP server with tool/resource definitionsqta.py: AI transpilation functions (async)utils.py: Account setup and circuit format utilities
Tools Provided:
| Tool | Description |
|---|---|
setup_ibm_quantum_account_tool |
Configure IBM Quantum account |
ai_routing_tool |
AI-powered circuit routing with SWAP insertion |
ai_clifford_synthesis_tool |
AI synthesis for Clifford circuits (H, S, CX; up to 9 qubits) |
ai_linear_function_synthesis_tool |
AI synthesis for Linear Function circuits (CX, SWAP; up to 9 qubits) |
ai_permutation_synthesis_tool |
AI synthesis for Permutation circuits (SWAP; 27, 33, 65 qubits) |
ai_pauli_network_synthesis_tool |
AI synthesis for Pauli Network circuits (up to 6 qubits) |
hybrid_ai_transpile_tool |
End-to-end hybrid transpilation combining Qiskit heuristics with AI passes |
Resources Provided:
| Resource URI | Description |
|---|---|
qiskit-ibm-transpiler://info |
Server capabilities and recommended workflow |
qiskit-ibm-transpiler://synthesis-types |
Documentation for all AI synthesis pass types (gates, qubit limits) |
Environment Variables:
QISKIT_IBM_TOKEN: IBM Quantum API token (required)
Circuit Format Support:
- Input: QASM 3.0 string or base64-encoded QPY
- Output: Base64-encoded QPY (for precision when chaining tools)
Purpose: Reinforcement learning-based quantum circuit synthesis
Directory: qiskit-gym-mcp-server/
Core Files:
server.py: FastMCP server entry pointserver_tools.py: All MCP tool definitionsserver_resources.py: All MCP resource definitionsapp.py: Application setup and server initializationgym_core.py: Environment creation (PermutationGym, LinearFunctionGym, CliffordGym)training.py: RL training session managementsynthesis.py: Circuit synthesis from trained modelsmodels.py: Model persistence (save/load)coupling_maps.py: Hardware presets and subtopology extractionstate.py: Singleton state managerconstants.py: Configuration defaultsutils.py: Utility functions
Tools Provided:
Environment Management:
| Tool | Description |
|---|---|
create_permutation_env_tool |
Create environment for SWAP routing |
create_linear_function_env_tool |
Create environment for CNOT synthesis |
create_clifford_env_tool |
Create environment for Clifford synthesis |
list_environments_tool |
List all created environments |
get_environment_info_tool |
Get details of a specific environment |
delete_environment_tool |
Delete an environment |
Training:
| Tool | Description |
|---|---|
start_training_tool |
Start RL training (PPO/AlphaZero) |
batch_train_environments_tool |
Train multiple environments |
get_training_status_tool |
Get status of a training session |
get_training_metrics_tool |
Get training metrics (rewards, episode lengths) |
wait_for_training_tool |
Wait for training to complete |
stop_training_tool |
Stop a running training session |
list_training_sessions_tool |
List all training sessions |
TensorBoard:
| Tool | Description |
|---|---|
list_tensorboard_experiments_tool |
List TensorBoard experiments |
get_tensorboard_metrics_tool |
Get metrics from TensorBoard logs |
start_tensorboard_tool |
Start TensorBoard server |
stop_tensorboard_tool |
Stop TensorBoard server |
get_tensorboard_status_tool |
Check TensorBoard server status |
Synthesis:
| Tool | Description |
|---|---|
synthesize_permutation_tool |
Generate optimal SWAP circuit |
synthesize_linear_function_tool |
Generate optimal CNOT circuit |
synthesize_clifford_tool |
Generate optimal Clifford circuit |
Model Management:
| Tool | Description |
|---|---|
save_model_tool |
Save trained model to disk |
load_model_tool |
Load model from disk |
list_saved_models_tool |
List models saved on disk |
list_loaded_models_tool |
List models loaded in memory |
delete_model_tool |
Delete a saved model |
get_model_info_tool |
Get detailed model information |
Coupling Maps & Utilities:
| Tool | Description |
|---|---|
create_coupling_map_tool |
Create a coupling map from edges or topology |
extract_subtopologies_tool |
Extract N-qubit subtopologies from hardware |
list_subtopology_shapes_tool |
List available subtopology shapes |
get_fake_backend_coupling_map_tool |
Get coupling map from a fake backend |
list_available_fake_backends_tool |
List available fake backends |
generate_random_permutation_tool |
Generate random permutation for testing |
generate_random_linear_function_tool |
Generate random linear function for testing |
generate_random_clifford_tool |
Generate random Clifford for testing |
convert_qpy_to_qasm3_tool |
Convert QPY to QASM3 |
convert_qasm3_to_qpy_tool |
Convert QASM3 to QPY |
Resources Provided:
| Resource URI | Description |
|---|---|
qiskit-gym://presets/coupling-maps |
Hardware presets (Heron, Nighthawk, grids) |
qiskit-gym://algorithms |
PPO, AlphaZero documentation |
qiskit-gym://policies |
BasicPolicy, Conv1dPolicy docs |
qiskit-gym://environments |
Environment type documentation |
qiskit-gym://workflows |
End-to-end workflow documentation |
qiskit-gym://training/sessions |
Active training sessions |
qiskit-gym://models |
Loaded models |
qiskit-gym://server/config |
Server configuration |
qiskit-gym://environments/{env_id} |
Specific environment info |
qiskit-gym://models/{model_name} |
Specific model info |
qiskit-gym://training/{session_id} |
Specific training session status |
Environment Variables:
QISKIT_GYM_MODEL_DIR: Model storage directory (default: ~/.qiskit-gym/models)QISKIT_GYM_TENSORBOARD_DIR: TensorBoard logs (default: ~/.qiskit-gym/runs)QISKIT_GYM_MAX_ITERATIONS: Maximum training iterations (default: 10000)QISKIT_GYM_MAX_QUBITS: Maximum qubits (default: 15)
Hardware Presets:
ibm_heron_r1(133 qubits, heavy-hex)ibm_heron_r2(156 qubits, heavy-hex)ibm_nighthawk(120 qubits, 10x12 grid)grid_3x3,grid_5x5,grid_10x10linear_5,linear_10
AI Assistant → MCP Client → transpile_circuit_tool
↓
transpiler.py (async functions)
↓
Qiskit preset pass managers
↓
Transpiled circuit (QPY format)
AI Assistant → MCP Client → search_docs_tool / get_page_tool
↓
data_fetcher.py (async functions)
↓
Qiskit Documentation Website
↓
Markdown-formatted documentation
AI Assistant → MCP Client → setup_ibm_quantum_account tool
↓
ibm_runtime.py (async functions)
↓
QiskitRuntimeService
↓
Backend info / Job management / Results
AI Assistant → MCP Client → ai_routing_tool / ai_*_synthesis_tool
↓
qta.py (async functions)
↓
qiskit-ibm-transpiler (AI passes)
↓
Optimized circuit (QPY format)
AI Assistant → MCP Client → create_*_env_tool → start_training_tool
↓ ↓
gym_core.py (envs) training.py (RLSynthesis)
↓
synthesize_*_tool
↓
Optimized circuit (QPY format)
-
Prerequisites:
- Python 3.10+ (3.11+ recommended)
- uv package manager
- IBM Quantum account and API token (for cloud servers)
- Git
-
Installation:
# Clone the repository git clone https://github.com/Qiskit/mcp-servers.git cd mcp-servers # Install all workspace dependencies uv sync # Or navigate to specific server cd qiskit-ibm-runtime-mcp-server uv sync
-
Configuration:
# Copy environment template cp .env.example .env # Edit .env and add your IBM Quantum API token # Get token from: https://quantum.cloud.ibm.com/
-
Running from Source:
# Run specific servers uv run qiskit-mcp-server uv run qiskit-ibm-runtime-mcp-server uv run qiskit-ibm-transpiler-mcp-server uv run qiskit-docs-mcp-server uv run qiskit-gym-mcp-server -
Interactive Testing:
# Test with MCP Inspector (requires Node.js) npx @modelcontextprotocol/inspector uv run qiskit-mcp-server
-
Python Standards:
- Python 3.10+ features allowed
- Async/await preferred for MCP operations
- Type hints required (mypy strict mode)
- Naming: snake_case for functions/variables, PascalCase for classes
- Docstrings for public functions (Google style)
-
License Header (required for all new files):
# This code is part of Qiskit. # # (C) Copyright IBM 2025. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. # # Any modifications or derivative works of this code must retain this # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals.
-
MCP Server Patterns:
- All servers use FastMCP framework
- Tools defined with
@mcp.tool()decorator - Resources defined with
@mcp.resource()decorator - Async functions for all MCP handlers
- Tool functions should delegate to core module functions
- Tool function names end with
_toolsuffix - Return type is
dict[str, Any]
-
Error Handling:
- Return
{"status": "error", "message": "..."}for errors - Return
{"status": "success", ...}for success - Provide clear error messages
- Log errors for debugging
- Handle network failures gracefully
- Validate inputs before API calls
- Return
-
Testing:
- Write tests in
tests/directory - Use pytest with async support (
pytest-asyncio) - Mock external APIs (
pytest-mock,respxfor HTTP) - Target 65%+ code coverage
- Never call real IBM Quantum APIs in unit tests
- Run tests:
./run_tests.shoruv run pytest
- Write tests in
-
Code Quality:
- Format with
ruff format - Lint with
ruff check - Type check with
mypy src/ - All checks must pass before committing
- Format with
When developing MCP servers that handle quantum computing resources:
-
Credential Management:
- Never hardcode API tokens or credentials in source code
- Use environment variables (
QISKIT_IBM_TOKEN) or secure credential files - Support fallback to saved credentials (
~/.qiskit/qiskit-ibm.json) - Never log or expose credentials in error messages or debug output
-
Input Validation:
- Validate all circuit inputs before processing (size, format, qubit count)
- Enforce configurable limits (
QISKIT_MCP_MAX_QUBITS,QISKIT_MCP_MAX_GATES) - Sanitize QASM strings before parsing
- Reject malformed or suspicious inputs early
-
API Security:
- Use HTTPS for all external API calls
- Implement proper error handling without leaking sensitive information
- Handle authentication failures gracefully
- Rate limit awareness for IBM Quantum API calls
-
Testing Security:
- Never use real credentials in unit tests
- Mock all external service calls
- Test error paths and edge cases
- Verify credential handling doesn't expose sensitive data
Comprehensive testing ensures MCP server reliability:
-
Test Organization:
tests/ ├── conftest.py # Shared fixtures and mocks ├── unit/ # Fast, isolated unit tests ├── integration/ # Tests with mocked external services └── test_*.py # Test files (pytest auto-discovery) -
Unit Tests:
- Test individual functions in isolation
- Mock all external dependencies
- Fast execution (no network calls)
- Target 65%+ code coverage
-
Integration Tests (marked with
@pytest.mark.integration):- Test tool and resource interactions
- Use mocked IBM Quantum services
- Verify end-to-end data flow
- Can be skipped with
pytest -m "not integration"
-
Common Fixtures (in
conftest.py):@pytest.fixture def mock_runtime_service(): """Mock QiskitRuntimeService with fake backends and jobs.""" ... @pytest.fixture def mock_env_vars(): """Set test environment variables.""" ... @pytest.fixture(autouse=True) def reset_service(): """Reset global service state between tests.""" ...
-
Async Testing Pattern:
@pytest.mark.asyncio async def test_async_tool(mock_service): """Test async MCP tool.""" result = await my_tool_function(params) assert result["status"] == "success"
-
Running Tests:
# All tests ./run_tests.sh # Unit tests only uv run pytest -m "not integration" # With coverage uv run pytest --cov=src --cov-report=html # Specific test file uv run pytest tests/test_server.py -v
-
Adding a New Tool:
# In server.py @mcp.tool() async def my_new_tool(param: str, optional_param: int = 10) -> dict[str, Any]: """Tool description for AI assistant. Args: param: Description of the parameter optional_param: Description with default behavior Returns: Dictionary with result data """ return await my_core_function(param, optional_param)
-
Adding a New Resource:
# In server.py @mcp.resource("protocol://path", mime_type="application/json") async def my_resource() -> dict[str, Any]: """Resource description.""" return await get_resource_data()
-
Adding Tests:
# In tests/test_*.py import pytest from unittest.mock import Mock, patch @pytest.mark.asyncio async def test_my_tool(mock_service_fixture): """Test description.""" with patch("my_package.module.ExternalService", return_value=mock_service_fixture): result = await my_function() assert result["status"] == "success"
-
Adding a New Server:
- Create new directory:
qiskit-<name>-mcp-server/ - Copy structure from existing server
- Create
pyproject.tomlwith unique package name - Add to workspace members in root
pyproject.toml - Implement server using FastMCP
- Add comprehensive tests
- Document in server-specific README.md
- Update main README.md with new server info
- Update GitHub CI/CD (see below)
- Create new directory:
When adding a new MCP server, you must update the following GitHub configurations:
-
Update
.github/workflows/test.yml:- Add server to the
lintjob's install, ruff check, ruff format, mypy, and bandit steps - Create a new
test-<name>job (copy from existing server job):test-<name>: runs-on: ubuntu-latest needs: lint strategy: matrix: python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] steps: - uses: actions/checkout@v4 - name: Install uv uses: astral-sh/setup-uv@v3 with: version: "latest" enable-cache: true - name: Set up Python ${{ matrix.python-version }} run: uv python install ${{ matrix.python-version }} - name: Install dependencies working-directory: ./qiskit-<name>-mcp-server run: uv sync --group dev --group test - name: Run tests working-directory: ./qiskit-<name>-mcp-server env: QISKIT_IBM_TOKEN: ${{ secrets.QISKIT_IBM_TOKEN }} run: uv run pytest tests/ -v --cov=src --cov-report=xml --cov-report=term-missing - name: Upload coverage uses: codecov/codecov-action@v3 with: file: ./qiskit-<name>-mcp-server/coverage.xml flags: <name> name: <name>-coverage
- Add server to the
-
Update
.github/workflows/publish-pypi.yml:- Add new option to
workflow_dispatchinputs - Create a new
publish-<name>job (copy from existing) - Use release tag pattern:
<name>(e.g., releases taggedtranspiler-v0.1.0) - Add to
publish-meta-packagejob'sneedsarray
- Add new option to
-
Update
.github/CODEOWNERS(if server has specific owners):/qiskit-<name>-mcp-server/ @owner1 @owner2 -
Release Tag Naming Convention:
Server Release Tag Pattern qiskit-mcp-server qiskit-v*qiskit-ibm-runtime-mcp-server runtime*qiskit-ibm-transpiler-mcp-server transpiler*qiskit-docs-mcp-server docs*qiskit-gym-mcp-server gym*Meta-package meta* -
GitHub Secrets Required:
QISKIT_IBM_TOKEN: IBM Quantum API token for integration tests- PyPI trusted publishing is configured (no token needed for publish)
-
Update
.github/workflows/publish-mcp-registry.yml:- Add new option to
workflow_dispatchinputs - Create a new
publish-<name>-mcp-registryjob (copy from existing) - Uses the same release tag pattern as PyPI publishing
- Add new option to
-
Create
server.jsonfor MCP Registry:{ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json", "name": "io.github.Qiskit/qiskit-<name>-mcp-server", "title": "Qiskit <Name> MCP Server", "description": "Short description (max 100 chars)", "version": "0.1.0", "websiteUrl": "https://github.com/Qiskit/mcp-servers/tree/main/qiskit-<name>-mcp-server", "repository": { "url": "https://github.com/Qiskit/mcp-servers", "source": "github", "id": "1051018539", "subfolder": "qiskit-<name>-mcp-server" }, "packages": [ { "registryType": "pypi", "identifier": "qiskit-<name>-mcp-server", "version": "0.1.0", "runtimeHint": "uvx", "transport": { "type": "stdio" }, "environmentVariables": [ { "name": "QISKIT_IBM_TOKEN", "description": "Your IBM Quantum API token", "isRequired": true, "isSecret": true } ] } ] }
# Navigate to specific server directory first
cd qiskit-mcp-server
# Install dependencies (including dev/test groups)
uv sync --group dev --group test
# Run all tests
./run_tests.sh
# OR
uv run pytest
# Run only unit tests (skip integration)
uv run pytest -m "not integration"
# Run only integration tests
uv run pytest -m "integration"
# Run with coverage report
uv run pytest --cov=src --cov-report=html
# Run specific test file
uv run pytest tests/test_transpiler.py -v
# Format code
uv run ruff format src/ tests/
# Lint code
uv run ruff check src/ tests/
# Type check
uv run mypy src/
# Fix linting issues automatically
uv run ruff check --fix src/ tests/-
Enable Debug Logging:
import logging logging.basicConfig(level=logging.DEBUG)
-
Test Individual Functions:
from qiskit_mcp_server.transpiler import transpile_circuit result = transpile_circuit.sync(qasm_circuit, optimization_level=2) print(result)
-
Use MCP Inspector:
npx @modelcontextprotocol/inspector uv run qiskit-mcp-server
-
Check Environment Variables:
echo $QISKIT_IBM_TOKEN
Each server is published independently to PyPI. See PUBLISHING.md for details.
Quick publishing workflow:
# Navigate to server directory
cd qiskit-mcp-server
# Update version in pyproject.toml
# Edit version = "0.2.0"
# Build package
uv build
# Publish to PyPI (requires credentials)
uv publish
# Or publish to Test PyPI first
uv publish --repository testpypiEach server is also published to the MCP Registry for discoverability by MCP clients.
Automated publishing (recommended):
- Publishing happens automatically via GitHub Actions when a release is created
- Uses the same release tags as PyPI (
qiskit-v*,runtime*,transpiler*,docs*,gym*) - Uses GitHub OIDC authentication (no secrets required)
Manual publishing:
# Trigger via GitHub Actions
gh workflow run "Publish to MCP Registry" -f package=all
# Or publish a specific server
gh workflow run "Publish to MCP Registry" -f package=qiskitserver.json configuration:
Each server has a server.json file that defines its MCP Registry metadata:
name: Reverse-DNS format (io.github.Qiskit/server-name)description: Short description (max 100 characters)version: Must match the version inpyproject.tomlpackages: PyPI package configuration with environment variablesrepository: GitHub repository metadata with subfolder path
When releasing a new version:
- Update version in
pyproject.toml - Update version in
server.json(must match) - Create and push release tag
- Both PyPI and MCP Registry workflows trigger automatically
- README.md: Overview, quick start, architecture
- CONTRIBUTING.md: Contribution guidelines
- CODE_OF_CONDUCT.md: Community guidelines
- PUBLISHING.md: PyPI publishing guide
- LICENSE: Apache 2.0 license
- AGENTS.md: This file
qiskit-mcp-server/README.md: Core Qiskit server docsqiskit-ibm-runtime-mcp-server/README.md: IBM Runtime server docsqiskit-ibm-transpiler-mcp-server/README.md: IBM Transpiler server docsqiskit-docs-mcp-server/README.md: Documentation server docsqiskit-gym-mcp-server/README.md: Qiskit Gym RL server docs
.github/CODEOWNERS: Default reviewers (@vabarbosa @cbjuan).github/PULL_REQUEST_TEMPLATE.md: PR template with checklist.github/ISSUE_TEMPLATE/bug_report.md: Bug report template.github/ISSUE_TEMPLATE/feature_request.md: Feature request template.github/workflows/test.yml: CI workflow (lint + test all servers).github/workflows/publish-pypi.yml: PyPI publishing workflow.github/workflows/publish-mcp-registry.yml: MCP Registry publishing workflow
- MCP Servers: Production-ready servers for quantum computing
- Async Operations: High-performance async-first design
- Type Safety: Full type checking with mypy
- Test Coverage: 65%+ coverage with comprehensive tests
- Multiple Servers: Independent, specialized servers
- Circuit Format Support: QASM3 and QPY for full fidelity
- Does NOT include AI agent implementations (only MCP servers)
- Does NOT execute quantum circuits directly (delegates to IBM Quantum or local simulators)
- Does NOT provide GUI or web interface
- Does NOT work without IBM Quantum credentials (for cloud services)
- Does NOT guarantee quantum hardware availability (depends on IBM)
- Async-first: All MCP operations are async
- Type-safe: Full mypy type checking
- Test-driven: Comprehensive test coverage
- Modern tooling: uv, ruff, pytest, FastMCP
- Modular: Independent servers, shared patterns
- Production-ready: Error handling, validation, logging
- Chainable: QPY output format for tool chaining
-
"401 Unauthorized" or authentication errors:
- Check: Is IBM Quantum token set correctly?
- Verify:
echo $QISKIT_IBM_TOKEN - Check: Token is valid on https://quantum.cloud.ibm.com/
- Try: Set token directly in
.envfile - For Runtime: Check saved credentials in
~/.qiskit/qiskit-ibm.json
-
"Module not found" errors:
- Ensure: Virtual environment is activated
- Run:
uv syncto install dependencies - Check: Running from correct directory
- Verify: Python version is 3.10+
-
Tests failing:
- Install test dependencies:
uv sync --group dev --group test - Check: No environment variables interfering
- Verify: Mock services are working
- Run: Individual test to isolate issue
- Install test dependencies:
-
MCP Inspector not working:
- Ensure: Node.js and npm are installed
- Check: Port 5173 is available
- Try:
npx @modelcontextprotocol/inspector --help - Verify: Server command is correct
-
Transpilation slow with optimization level 3:
- Use level 2 for most use cases
- Level 3 can be very slow for circuits with >20 qubits or >500 gates
- Use
compare_optimization_levelsto find optimal level
# Check Python version
python --version
# Check uv installation
uv --version
# List installed packages
uv pip list
# Check environment variables
env | grep -i qiskit
# Verify package installation
uv run python -c "import qiskit_mcp_server; print('OK')"
# Test connectivity to IBM Quantum
uv run python -c "
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
print(f'Connected. Backends: {len(service.backends())}')
"qiskit-mcp-servers/
├── .claude/
│ └── skills/
│ └── qiskit-mcp-dev/
│ └── SKILL.md # Claude Code development skill
├── .github/
│ ├── CODEOWNERS # Default PR reviewers
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ └── feature_request.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ └── workflows/
│ ├── test.yml # CI: lint + test all servers
│ ├── publish-pypi.yml # CD: publish to PyPI on release
│ └── publish-mcp-registry.yml # CD: publish to MCP Registry on release
├── qiskit-mcp-server/
│ ├── src/qiskit_mcp_server/
│ │ ├── __init__.py
│ │ ├── server.py # FastMCP server
│ │ ├── transpiler.py # Core transpilation
│ │ ├── circuit_serialization.py # QASM3/QPY utilities
│ │ └── utils.py # Basis gates & topology presets
│ ├── tests/
│ │ ├── conftest.py
│ │ ├── test_transpiler.py
│ │ └── test_circuit_serialization.py
│ ├── examples/
│ │ ├── README.md
│ │ ├── langchain_agent.ipynb
│ │ └── langchain_agent.py
│ ├── pyproject.toml
│ ├── server.json # MCP Registry metadata
│ ├── LICENSE
│ ├── README.md
│ └── run_tests.sh
├── qiskit-docs-mcp-server/
│ ├── src/qiskit_docs_mcp_server/
│ │ ├── __init__.py
│ │ ├── server.py # FastMCP server + lifespan
│ │ ├── data_fetcher.py # Documentation fetching & search
│ │ ├── constants.py # URL config, timeouts
│ │ ├── html_processing.py # HTML-to-Markdown conversion
│ │ ├── http.py # Shared httpx client
│ │ └── sitemap.py # Dynamic sitemap discovery
│ ├── tests/
│ │ ├── conftest.py
│ │ ├── test_data_fetcher.py
│ │ └── test_server.py
│ ├── examples/
│ │ ├── README.md
│ │ ├── langchain_agent.ipynb
│ │ └── langchain_agent.py
│ ├── pyproject.toml
│ ├── LICENSE
│ ├── README.md
│ └── run_tests.sh
├── qiskit-ibm-runtime-mcp-server/
│ ├── src/qiskit_ibm_runtime_mcp_server/
│ │ ├── __init__.py
│ │ ├── server.py # FastMCP server
│ │ ├── ibm_runtime.py # Core async functions
│ │ └── utils.py # Account & circuit utilities
│ ├── tests/
│ │ ├── conftest.py
│ │ ├── test_server.py
│ │ ├── test_integration.py
│ │ └── test_sync.py
│ ├── examples/
│ │ ├── README.md
│ │ ├── langchain_agent.ipynb
│ │ └── langchain_agent.py
│ ├── pyproject.toml
│ ├── pytest.ini
│ ├── LICENSE
│ ├── README.md
│ └── run_tests.sh
├── qiskit-ibm-transpiler-mcp-server/
│ ├── src/qiskit_ibm_transpiler_mcp_server/
│ │ ├── __init__.py
│ │ ├── server.py # FastMCP server
│ │ ├── qta.py # AI transpilation functions
│ │ └── utils.py # Utilities
│ ├── tests/
│ │ ├── conftest.py
│ │ ├── unit/ # Unit tests
│ │ ├── integration/ # Integration tests
│ │ ├── qasm/ # Test QASM files
│ │ └── utils/ # Test helpers
│ ├── examples/
│ │ ├── README.md
│ │ ├── langchain_agent.ipynb
│ │ └── langchain_agent.py
│ ├── pyproject.toml
│ ├── pytest.ini
│ ├── LICENSE
│ ├── README.md
│ └── run_tests.sh
├── qiskit-gym-mcp-server/
│ ├── src/qiskit_gym_mcp_server/
│ │ ├── __init__.py
│ │ ├── server.py # FastMCP server entry point
│ │ ├── server_tools.py # All MCP tool definitions
│ │ ├── server_resources.py # All MCP resource definitions
│ │ ├── app.py # Application setup
│ │ ├── gym_core.py # Environment creation
│ │ ├── training.py # RL training functions
│ │ ├── synthesis.py # Circuit synthesis
│ │ ├── models.py # Model persistence
│ │ ├── coupling_maps.py # Hardware presets
│ │ ├── state.py # Singleton state manager
│ │ ├── constants.py # Configuration
│ │ └── utils.py # Utilities
│ ├── tests/
│ │ ├── conftest.py
│ │ └── test_*.py
│ ├── examples/
│ │ ├── README.md
│ │ ├── langchain_agent.ipynb
│ │ └── langchain_agent.py
│ ├── pyproject.toml
│ ├── README.md
│ └── run_tests.sh
├── examples/
│ ├── README.md
│ ├── quantum_volume_optimizer.ipynb
│ └── quantum_volume_optimizer.py
├── docs/
│ └── videos/ # Demo videos for README
├── src/
│ └── qiskit_mcp_servers/ # Meta-package
├── pyproject.toml # Workspace config & meta-package
├── mypy.ini # Shared mypy config
├── ruff.toml # Shared ruff config
├── README.md
├── AGENTS.md
├── CONTRIBUTING.md
├── CODE_OF_CONDUCT.md
├── PUBLISHING.md
├── LICENSE
├── uv.lock
└── .gitignore
When helping with this repository:
- Identify the correct server: Ask which server the user is working with or check context
- Read before suggesting: Use Read tool on relevant files before making changes
- Follow existing patterns: Match code style and architecture from the specific server
- Don't hallucinate features: Only reference capabilities that exist in the codebase
- Check documentation: Point to correct README (main or server-specific)
- Test suggestions: Verify code works with the async patterns
- Respect server boundaries: Don't mix code between different servers
- Use proper tools: Grep for searching, Read for files, Edit for changes
- Async by default: MCP functions should be async
- Maintain independence: Each server should remain independently runnable
- Include license headers: All new files need the Apache 2.0 header
- Mock external services: Never call real IBM Quantum APIs in tests
Adding a tool? → Edit server.py, add @mcp.tool() decorated function
Adding a resource? → Edit server.py, add @mcp.resource("uri") decorated function
Adding tests? → Write in tests/test_*.py with pytest, mock external services
Updating docs? → Server-specific in <server>/README.md, general in main README.md
Publishing? → See PUBLISHING.md
New server? → Copy structure from existing, add to workspace members, update all names/imports
Architecture questions? → Read server.py and main README.md
Circuit format? → Use QASM3 for human-readable, QPY for chaining tools (preserves exact parameters)