Metadata-Version: 2.4
Name: qiskit-code-assistant-mcp-server
Version: 0.4.0
Summary: MCP server for the Qiskit Code Assistant
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-code-assistant-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: httpx>=0.25.0
Requires-Dist: nest-asyncio>=1.5.0
Requires-Dist: python-dotenv>=1.0.0
Provides-Extra: all
Requires-Dist: bandit[toml]>=1.7.0; extra == 'all'
Requires-Dist: httpx>=0.25.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: respx>=0.20.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: httpx>=0.25.0; 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'
Requires-Dist: respx>=0.20.0; extra == 'test'
Description-Content-Type: text/markdown

# qiskit-code-assistant-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-code-assistant-mcp-server%2Fversions%2Flatest&query=%24.server.version&label=MCP%20Registry&logo=modelcontextprotocol)](https://registry.modelcontextprotocol.io/?q=io.github.Qiskit%2Fqiskit-code-assistant-mcp-server)

<!-- mcp-name: io.github.Qiskit/qiskit-code-assistant-mcp-server -->

MCP server for Qiskit Code Assistant


## Components


### Tools

The server implements four tools:
- `accept_model_disclaimer_tool`: Accept the disclaimer for a given model
- `get_completion_tool`: Get completion for a given prompt
- `get_rag_completion_tool`: Get RAG completion for answering conceptual or descriptive questions about Qiskit or Quantum
- `accept_completion_tool`: Accept a given completion


## Prerequisites

- Python 3.10 or higher
- [uv](https://astral.sh/uv) package manager (recommended)
- IBM Quantum account and API token
- Access to Qiskit Code Assistant service

## Installation

### Install from PyPI

The easiest way to install is via pip:

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

### Install from Source

This project uses [uv](https://astral.sh/uv) for virtual environments and dependencies management. If you don't have `uv` installed, check out the instructions in <https://docs.astral.sh/uv/getting-started/installation/>

### Setting up the Project with uv

1. **Initialize or sync the project**:
   ```bash
   # This will create a virtual environment and install dependencies
   uv sync
   ```

2. **Configure environment variables**:
   ```bash
   # Copy the example environment file
   cp .env.example .env
   
   # Edit .env and add your IBM Quantum API token
   # Get your token from: https://cloud.quantum.ibm.com/
   ```

## Configuration

### Environment Variables

The server can be configured using environment variables in your `.env` file:

- `QISKIT_IBM_TOKEN` - Your IBM Quantum API token (required)
- `QCA_TOOL_API_BASE` - Qiskit Code Assistant API base URL (default: `https://qiskit-code-assistant.quantum.ibm.com`)
- `QCA_TOOL_MODEL_NAME` - Default model name (default: `mistral-small-3.2-24b-qiskit`)
- `QCA_REQUEST_TIMEOUT` - Request timeout in seconds (default: `30.0`)
- `QCA_MCP_DEBUG_LEVEL` - Logging level: DEBUG, INFO, WARNING, ERROR, CRITICAL (default: `INFO`)

### Model Selection

The server includes an **automatic model availability guardrail** that:
- Checks available models from the Qiskit Code Assistant service at startup
- Uses the configured `QCA_TOOL_MODEL_NAME` if available
- Automatically falls back to the first available model if the default is unavailable
- Logs warnings when using a fallback model
- Gracefully handles API errors by using the configured default

This ensures the server can start and function even when the default model is temporarily unavailable.

## Quick Start

### Running the Server

```bash
uv run qiskit-code-assistant-mcp-server
```

The server will start and listen for MCP connections.

### Synchronous Usage

For frameworks that don't support async operations, all async functions have a `.sync` attribute for synchronous execution:

```python
from qiskit_code_assistant_mcp_server.qca import (
    get_completion,
    get_rag_completion,
    list_models
)

# Use .sync for synchronous execution
result = get_completion.sync("Write a quantum circuit for a Bell state")
print(result)

# Works in Jupyter notebooks (handles nested event loops automatically)
rag_result = get_rag_completion.sync("What is quantum entanglement?")
print(rag_result)

# List available models
models = list_models.sync()
print(models)
```

**Available functions (all support `.sync`):**
- `list_models()` - List available models
- `get_model(model_id)` - Get model info
- `get_completion(prompt)` - Get code completion
- `get_rag_completion(prompt)` - Get RAG-based completion
- `accept_completion(completion_id)` - Accept a completion
- `get_service_status()` - Get service status

**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 (QISKIT_IBM_TOKEN, OPENAI_API_KEY, etc.)
load_dotenv()

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

    # Use persistent session for efficient tool calls
    async with mcp_client.session("qiskit-code-assistant") 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("Write a quantum circuit that creates a Bell state")
        print(response)

asyncio.run(main())
```

For more LLM providers (Anthropic, Google, Ollama, Watsonx) and detailed examples including Jupyter notebooks, see the [examples/](examples/) directory.


### Testing and debugging the server

> _**Note**: to launch the MCP inspector you will need to have [`node` and `npm`](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)_

1. From a terminal, go into the cloned repo directory

1. Switch to the virtual environment

    ```sh
    source .venv/bin/activate
    ```

1. Run the MCP Inspector:

    ```sh
    npx @modelcontextprotocol/inspector uv run qiskit-code-assistant-mcp-server
    ```

1. Open your browser to the URL shown in the console message e.g.,

    ```
    MCP Inspector is up and running at http://localhost:5173
    ```

## Testing

This project includes comprehensive unit and integration tests.

### Running Tests

**Quick test run:**
```bash
./run_tests.sh
```

**Manual test commands:**
```bash
# Install test dependencies
uv sync --group dev --group test

# Run all tests
uv run pytest

# Run only unit tests
uv run pytest -m "not integration"

# Run only integration tests
uv run pytest -m "integration"

# Run tests with coverage
uv run pytest --cov=src --cov-report=html

# Run specific test file
uv run pytest tests/test_qca.py -v
```

### Test Structure

- `tests/test_qca.py` - Unit tests for QCA functions
- `tests/test_utils.py` - Unit tests for utility functions
- `tests/test_constants.py` - Unit tests for configuration
- `tests/test_sync.py` - Unit tests for synchronous execution
- `tests/test_integration.py` - Integration tests
- `tests/conftest.py` - Test fixtures and configuration

### Test Coverage

The test suite covers:
- ✅ All QCA API interactions
- ✅ Model selection and availability guardrail
- ✅ Error handling and validation
- ✅ HTTP client management
- ✅ Synchronous execution (`.sync` methods)
- ✅ Configuration validation
- ✅ Integration scenarios
- ✅ Resource and tool handlers

## Resources

- [Qiskit Code Assistant](https://docs.quantum.ibm.com/guides/qiskit-code-assistant)
- [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction)
- [MCP Inspector](https://github.com/modelcontextprotocol/inspector)
