Qiskit MCP Server

A Model Context Protocol (MCP) server that provides quantum circuit transpilation capabilities using Qiskit's pass managers. This server enables AI assistants to optimize quantum circuits for various hardware targets.
Features
- Circuit Transpilation: Transpile quantum circuits with configurable optimization levels (0-3)
- Preset Basis Gates: Support for IBM Eagle, IBM Heron, ion trap, and other basis gate sets
- Topology Support: Built-in support for linear, ring, grid, and custom coupling maps
- Circuit Analysis: Analyze circuit complexity without transpilation
- Optimization Comparison: Compare results across all optimization levels
- Dual API: Supports both async (MCP) and sync (Jupyter, scripts) usage
Prerequisites
- Python 3.10 or higher
- uv package manager (recommended) or pip
Installation
From PyPI (when published)
pip install qiskit-mcp-server
From Source
git clone https://github.com/Qiskit/mcp-servers.git
cd mcp-servers/qiskit-mcp-server
uv sync
pip install -e .
Quick Start
Running the MCP Server
uv run qiskit-mcp-server
qiskit-mcp-server
Claude Desktop Configuration
Add to your Claude Desktop configuration (claude_desktop_config.json):
{
"mcpServers": {
"qiskit": {
"command": "uv",
"args": [
"--directory",
"/path/to/qiskit-mcp-servers/qiskit-mcp-server",
"run",
"qiskit-mcp-server"
]
}
}
}
Usage Examples
Async Usage (MCP Server / FastAPI)
from qiskit_mcp_server.transpiler import transpile_circuit
qasm = """OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
creg c[2];
h q[0];
cx q[0], q[1];
measure q -> c;
"""
result = await transpile_circuit(qasm)
result = await transpile_circuit(
qasm,
optimization_level=3,
basis_gates="ibm_heron",
coupling_map="linear"
)
from qiskit import QuantumCircuit
from qiskit_mcp_server import dump_qpy_circuit
from qiskit_mcp_server.transpiler import transpile_circuit
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
qpy_circuit = dump_qpy_circuit(qc)
result = await transpile_circuit(qpy_circuit, circuit_format="qpy")
transpiled_qpy = result["transpiled_circuit"]["circuit_qpy"]
result2 = await transpile_circuit(transpiled_qpy, circuit_format="qpy", optimization_level=3)
Sync Usage (Scripts, Jupyter)
from qiskit_mcp_server.transpiler import transpile_circuit, analyze_circuit
result = transpile_circuit.sync(qasm, optimization_level=2)
analysis = analyze_circuit.sync(qasm)
print(f"Circuit depth: {analysis['circuit_info']['depth']}")
print(f"Two-qubit gates: {analysis['gate_categories']['two_qubit_gates']}")
Compare Optimization Levels
from qiskit_mcp_server.transpiler import compare_optimization_levels
comparison = compare_optimization_levels.sync(qasm)
for level in range(4):
result = comparison['optimization_results'][f'level_{level}']
print(f"Level {level}: depth={result['depth']}, size={result['size']}")
LangChain Integration Example:
Note: To run LangChain examples you will need to install the dependencies:
pip install langchain langchain-mcp-adapters langchain-openai python-dotenv
import asyncio
import os
from langchain.agents import create_agent
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain_mcp_adapters.tools import load_mcp_tools
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
load_dotenv()
SAMPLE_BELL = """
OPENQASM 3.0;
include "stdgates.inc";
qubit[2] q;
h q[0];
cx q[0], q[1];
"""
async def main():
mcp_client = MultiServerMCPClient({
"qiskit": {
"transport": "stdio",
"command": "qiskit-mcp-server",
"args": [],
"env": {},
}
})
async with mcp_client.session("qiskit") as session:
tools = await load_mcp_tools(session)
llm = ChatOpenAI(model="gpt-5.2", temperature=0)
agent = create_agent(llm, tools)
response = await agent.ainvoke(f"Transpile this circuit for IBM Heron: {SAMPLE_BELL}")
print(response)
asyncio.run(main())
For more LLM providers (Anthropic, Google, Ollama, Watsonx) and detailed examples including Jupyter notebooks, see the examples/ directory.
API Reference
| Tool | Description |
|---|
transpile_circuit_tool | Transpile a circuit with configurable optimization |
analyze_circuit_tool | Analyze circuit structure without transpiling |
compare_optimization_levels_tool | Compare all optimization levels (0-3) |
load_circuit_from_qasm_tool | Load a circuit from OpenQASM 2.0 or 3.0 string, returning QPY and metadata |
export_circuit_to_qasm_tool | Export a QPY circuit to OpenQASM 2.0 or 3.0 format |
convert_qpy_to_qasm3_tool | Convert a base64-encoded QPY circuit to QASM3 |
convert_qasm3_to_qpy_tool | Convert a QASM3 (or QASM2) circuit to base64-encoded QPY |
Resources
| 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 |
Core Functions
Transpile a quantum circuit using Qiskit's preset pass managers.
Parameters:
circuit: Quantum circuit as QASM3 string, base64-encoded QPY, or QASM2 string (max 100 qubits, 10,000 gates)
optimization_level: 0-3 (default: 2)
- 0: No optimization, only basis gate decomposition (fastest)
- 1: Light optimization with default layout
- 2: Medium optimization with noise-aware layout (recommended)
- 3: Heavy optimization for best results (can be slow for large circuits)
basis_gates: List of gate names or preset ("ibm_default", "ibm_heron", etc.)
coupling_map: List of edges or topology name ("linear", "ring", "grid", "full")
initial_layout: List of physical qubit indices (length must match circuit qubits)
seed_transpiler: Random seed for reproducibility
circuit_format: Format of the input circuit ("qasm3" or "qpy"). Defaults to "qasm3". When "qasm3" is specified, QASM2 is also accepted as a fallback.
Returns: Dictionary with original/transpiled circuit info and optimization metrics
Note: Level 3 optimization can be very slow for circuits with >20 qubits or >500 gates. Use level 2 for faster results with good quality.
Analyze circuit structure and complexity.
Returns: Dictionary with gate counts, depth, and categorization (single/two/multi-qubit gates)
Compare transpilation results across all optimization levels.
Returns: Dictionary comparing depth, size, and gates for levels 0-3
The server supports two circuit formats for input:
| Format | Description |
|---|
qasm3 | OpenQASM 3.0 string (with QASM2 fallback). Human-readable text format. |
qpy | Base64-encoded QPY binary format. Preserves exact parameters and metadata. |
QPY output: All tools return circuits in QPY format (base64-encoded) for precision when chaining tools/servers.
When to use each format:
- QASM3 (input): Best for human-readable circuits and initial input
- QPY (input/output): Best for preserving exact numerical parameters when chaining tools/servers
Converting QPY to Human-Readable QASM3
To view a QPY circuit output in human-readable format, use the qpy_to_qasm3 utility:
from qiskit_mcp_server import qpy_to_qasm3
from qiskit_mcp_server.transpiler import transpile_circuit
result = transpile_circuit.sync(qasm_circuit, optimization_level=2)
qpy_output = result["transpiled_circuit"]["circuit_qpy"]
conversion = qpy_to_qasm3(qpy_output)
if conversion["status"] == "success":
print(conversion["qasm3"])
Converting QASM3 to QPY
To convert a QASM circuit to QPY format (for full fidelity when chaining tools), use qasm3_to_qpy:
from qiskit_mcp_server import qasm3_to_qpy
qasm_circuit = '''
OPENQASM 3.0;
include "stdgates.inc";
qubit[2] q;
h q[0];
cx q[0], q[1];
'''
result = qasm3_to_qpy(qasm_circuit)
if result["status"] == "success":
qpy_string = result["circuit_qpy"]
Available Basis Gate Sets
| Preset | Gates | Description |
|---|
ibm_eagle | id, rz, sx, x, ecr, reset | IBM Eagle r3 (127 qubits, uses ECR) |
ibm_heron | id, rz, sx, x, cz, reset | IBM Heron (133-156 qubits, uses CZ) |
ibm_legacy | id, rz, sx, x, cx, reset | Older IBM systems (uses CX) |
You can also provide a custom list of gate names for other hardware targets.
Available Topologies
| Topology | Description |
|---|
linear | Chain connectivity (qubit i ↔ i+1) |
ring | Linear with wraparound |
grid | 2D grid connectivity |
heavy_hex | IBM heavy-hex topology (Eagle/Heron architecture) |
full | All-to-all connectivity |
Circuit Size Limits
To ensure reliable performance, the server enforces the following limits:
| Limit | Default | Environment Variable |
|---|
| Maximum qubits | 100 | QISKIT_MCP_MAX_QUBITS |
| Maximum gates | 10,000 | QISKIT_MCP_MAX_GATES |
Circuits exceeding these limits will return an error with a descriptive message.
You can override these limits via environment variables:
export QISKIT_MCP_MAX_QUBITS=200
export QISKIT_MCP_MAX_GATES=50000
| Optimization Level | Use Case | Performance |
|---|
| 0 | Quick iterations, debugging | Fastest |
| 1 | Development, prototyping | Fast |
| 2 | Production use (recommended) | Balanced |
| 3 | Critical applications, small circuits | Slowest |
Tips:
- Use level 2 for most use cases (best balance of quality and speed)
- Use level 3 only when circuit quality is critical AND circuit is small (<20 qubits, <500 gates)
- Use level 0 or 1 for rapid prototyping and development
- The
compare_optimization_levels tool helps identify the best level for your specific circuit
Transpilation Stages
The Qiskit transpiler processes circuits through six stages:
- init: Decompose multi-qubit gates to 1 and 2-qubit operations
- layout: Map virtual qubits to physical qubits
- routing: Insert SWAP gates for hardware connectivity
- translation: Convert to target basis gates
- optimization: Reduce gate count and circuit depth
- scheduling: Add timing and delay instructions
Testing
uv run pytest tests/ -v
uv run pytest tests/ --cov=src --cov-report=term-missing
uv run pytest tests/test_transpiler.py::TestTranspileCircuit -v
Development
uv sync --group dev --group test
uv run ruff check src tests
uv run ruff format --check src tests
uv run mypy src
./run_tests.sh
Contributing
Contributions are welcome! Please see the CONTRIBUTING.md guide in the root of the repository.
License
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.