Metadata-Version: 2.4
Name: qiskit-mcp-server
Version: 0.3.0
Summary: MCP server for Qiskit quantum computing capabilities with circuit serialization utilities
Project-URL: Homepage, https://github.com/Qiskit/mcp-servers
Project-URL: Repository, https://github.com/Qiskit/mcp-servers
Project-URL: Documentation, https://github.com/Qiskit/mcp-servers/tree/main/qiskit-mcp-server#readme
Project-URL: Bug Tracker, https://github.com/Qiskit/mcp-servers/issues
Author-email: "Quantum+AI Team. IBM Quantum" <Quantum.Plus.AI@ibm.com>
License: Apache-2.0
License-File: LICENSE
Requires-Python: <3.15,>=3.10
Requires-Dist: fastmcp<3,>=2.8.1
Requires-Dist: nest-asyncio>=1.5.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: qiskit-qasm3-import>=0.5.0
Requires-Dist: qiskit>=1.3.0
Provides-Extra: all
Requires-Dist: bandit[toml]>=1.7.0; extra == 'all'
Requires-Dist: mypy>=1.15.0; extra == 'all'
Requires-Dist: pre-commit>=3.5.0; extra == 'all'
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'all'
Requires-Dist: pytest-cov>=4.1.0; extra == 'all'
Requires-Dist: pytest-mock>=3.11.0; extra == 'all'
Requires-Dist: pytest>=7.4.0; extra == 'all'
Requires-Dist: ruff>=0.11.13; extra == 'all'
Provides-Extra: dev
Requires-Dist: bandit[toml]>=1.7.0; extra == 'dev'
Requires-Dist: mypy>=1.15.0; extra == 'dev'
Requires-Dist: pre-commit>=3.5.0; extra == 'dev'
Requires-Dist: ruff>=0.11.13; extra == 'dev'
Provides-Extra: test
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'test'
Requires-Dist: pytest-cov>=4.1.0; extra == 'test'
Requires-Dist: pytest-mock>=3.11.0; extra == 'test'
Requires-Dist: pytest>=7.4.0; extra == 'test'
Description-Content-Type: text/markdown

# Qiskit MCP Server

[![MCP Registry](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fregistry.modelcontextprotocol.io%2Fv0.1%2Fservers%2Fio.github.Qiskit%252Fqiskit-mcp-server%2Fversions%2Flatest&query=%24.server.version&label=MCP%20Registry&logo=modelcontextprotocol)](https://registry.modelcontextprotocol.io/?q=io.github.Qiskit%2Fqiskit-mcp-server)

<!-- mcp-name: io.github.Qiskit/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](https://docs.astral.sh/uv/) package manager (recommended) or pip

## Installation

### From PyPI (when published)

```bash
pip install qiskit-mcp-server
```

### From Source

```bash
# Clone the repository
git clone https://github.com/Qiskit/mcp-servers.git
cd mcp-servers/qiskit-mcp-server

# Install with uv
uv sync

# Or with pip
pip install -e .
```

## Quick Start

### Running the MCP Server

```bash
# With uv
uv run qiskit-mcp-server

# Or directly
qiskit-mcp-server
```

### Claude Desktop Configuration

Add to your Claude Desktop configuration (`claude_desktop_config.json`):

```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)

```python
from qiskit_mcp_server.transpiler import transpile_circuit

# Simple Bell state circuit (QASM2 - automatically detected)
qasm = """OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
creg c[2];
h q[0];
cx q[0], q[1];
measure q -> c;
"""

# Transpile with default settings (optimization level 2, QASM3 format)
result = await transpile_circuit(qasm)

# Transpile for IBM Heron processor
result = await transpile_circuit(
    qasm,
    optimization_level=3,
    basis_gates="ibm_heron",
    coupling_map="linear"
)
```

### Using QPY Format

```python
from qiskit import QuantumCircuit
from qiskit_mcp_server import dump_qpy_circuit
from qiskit_mcp_server.transpiler import transpile_circuit

# Create a circuit programmatically
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])

# Convert to QPY (preserves exact parameters and metadata)
qpy_circuit = dump_qpy_circuit(qc)

# Transpile using QPY format
result = await transpile_circuit(qpy_circuit, circuit_format="qpy")
# Result includes transpiled circuit in QPY format (for chaining)
transpiled_qpy = result["transpiled_circuit"]["circuit_qpy"]

# Chain to another operation using QPY
result2 = await transpile_circuit(transpiled_qpy, circuit_format="qpy", optimization_level=3)
```

### Sync Usage (Scripts, Jupyter)

```python
from qiskit_mcp_server.transpiler import transpile_circuit, analyze_circuit

# All async functions have a .sync attribute
result = transpile_circuit.sync(qasm, optimization_level=2)

# Analyze circuit without transpiling
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

```python
from qiskit_mcp_server.transpiler import compare_optimization_levels

# Compare all optimization levels (0-3) for your circuit
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:
> ```bash
> pip install langchain langchain-mcp-adapters langchain-openai python-dotenv
> ```

```python
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 environment variables (OPENAI_API_KEY, etc.)
load_dotenv()

# Sample Bell state circuit
SAMPLE_BELL = """
OPENQASM 3.0;
include "stdgates.inc";
qubit[2] q;
h q[0];
cx q[0], q[1];
"""

async def main():
    # Configure MCP client
    mcp_client = MultiServerMCPClient({
        "qiskit": {
            "transport": "stdio",
            "command": "qiskit-mcp-server",
            "args": [],
            "env": {},
        }
    })

    # Use persistent session for efficient tool calls
    async with mcp_client.session("qiskit") as session:
        tools = await load_mcp_tools(session)

        # Create agent with LLM
        llm = ChatOpenAI(model="gpt-5.2", temperature=0)
        agent = create_agent(llm, tools)

        # Run a query
        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/](examples/) directory.

## API Reference

### Tools

| 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_circuit(circuit, optimization_level=2, basis_gates=None, coupling_map=None, initial_layout=None, seed_transpiler=None, circuit_format="qasm3")`

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(circuit, circuit_format="qasm3")`

Analyze circuit structure and complexity.

**Returns:** Dictionary with gate counts, depth, and categorization (single/two/multi-qubit gates)

#### `compare_optimization_levels(circuit, circuit_format="qasm3")`

Compare transpilation results across all optimization levels.

**Returns:** Dictionary comparing depth, size, and gates for levels 0-3

### Circuit Format Support

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:

```python
from qiskit_mcp_server import qpy_to_qasm3
from qiskit_mcp_server.transpiler import transpile_circuit

# Transpile a circuit (returns QPY format)
result = transpile_circuit.sync(qasm_circuit, optimization_level=2)
qpy_output = result["transpiled_circuit"]["circuit_qpy"]

# Convert to human-readable QASM3
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`:

```python
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];
'''

# Convert to QPY format
result = qasm3_to_qpy(qasm_circuit)
if result["status"] == "success":
    qpy_string = result["circuit_qpy"]
    # Use qpy_string with tools that accept QPY input
```

### 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 |

## Limits and Performance

### 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:

```bash
# Allow up to 200 qubits and 50,000 gates
export QISKIT_MCP_MAX_QUBITS=200
export QISKIT_MCP_MAX_GATES=50000
```

### Performance Recommendations

| 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:

1. **init**: Decompose multi-qubit gates to 1 and 2-qubit operations
2. **layout**: Map virtual qubits to physical qubits
3. **routing**: Insert SWAP gates for hardware connectivity
4. **translation**: Convert to target basis gates
5. **optimization**: Reduce gate count and circuit depth
6. **scheduling**: Add timing and delay instructions

## Testing

```bash
# Run all tests
uv run pytest tests/ -v

# Run with coverage
uv run pytest tests/ --cov=src --cov-report=term-missing

# Run specific test class
uv run pytest tests/test_transpiler.py::TestTranspileCircuit -v
```

## Development

```bash
# Install dev dependencies
uv sync --group dev --group test

# Run linting
uv run ruff check src tests
uv run ruff format --check src tests

# Run type checking
uv run mypy src

# Run all checks
./run_tests.sh
```

## Contributing

Contributions are welcome! Please see the [CONTRIBUTING.md](../CONTRIBUTING.md) guide in the root of the repository.

## License

This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
