qiskit-mcp-dev — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited qiskit-mcp-dev (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
When helping with MCP server development in this repository:
server.py and core modules before adding new functionalityasync def, delegate to core module functions# 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.Tools go in server.py and delegate to async functions in the core module:
# Example: from qiskit_<name>_mcp_server.<core> import my_function
from qiskit_ibm_runtime_mcp_server.ibm_runtime import my_function
@mcp.tool()
async def my_tool_name(param: str, optional_param: int = 10) -> dict[str, Any]:
"""Clear description of what this tool does.
Args:
param: Description of the parameter
optional_param: Description with default behavior
Returns:
Description of the return structure
"""
return await my_function(param, optional_param)Key patterns:
_tool suffixdict[str, Any]All tools return consistent response format:
# Success
return {"status": "success", "data": result, ...}
# Error
return {"status": "error", "message": "Description of what went wrong"}@mcp.resource("protocol://path", mime_type="application/json")
async def get_resource_name() -> dict[str, Any]:
"""Description of the resource."""
return await get_data_from_core_module()Tests use pytest with mocked services. See tests/conftest.py for fixtures.
import pytest
from unittest.mock import Mock, patch
@pytest.mark.asyncio
async def test_my_tool(mock_service):
"""Test description."""
with patch(
"qiskit_<name>_mcp_server.<core>.ExternalService",
return_value=mock_service,
):
result = await my_function()
assert result["status"] == "success"Common fixture patterns in conftest.py (names vary by server):
mock_*_service - Mocked external service (e.g., mock_runtime_service, mock_http_client)mock_env_vars - Sets environment variables like QISKIT_IBM_TOKENreset_* - Resets global state between tests (often autouse=True)Run from the server directory:
uv run ruff format src/ tests/ # Format
uv run ruff check src/ tests/ # Lint
uv run mypy src/ # Type check
uv run pytest # TestWhen creating a new server qiskit-<name>-mcp-server:
pyproject.toml: [tool.uv.workspace]
members = [..., "qiskit-<name>-mcp-server"]README.md - Setup instructions and usagelangchain_agent.ipynb - Interactive Jupyter tutoriallangchain_agent.py - CLI agent supporting multiple LLM providers.github/workflows/test.yml:lint job (install, ruff, mypy, bandit steps)test-<name> job.github/workflows/publish-pypi.yml:workflow_dispatch optionspublish-<name> jobpublish-meta-package needs array.github/workflows/publish-mcp-registry.yml:workflow_dispatch optionspublish-<name>-mcp-registry jobqiskit-<name>-mcp-server/
├── src/qiskit_<name>_mcp_server/
│ ├── __init__.py # Package init, version
│ ├── server.py # FastMCP server, @mcp.tool() and @mcp.resource()
│ └── <core>.py # Async business logic
├── tests/
│ ├── conftest.py # Fixtures for mocking
│ └── test_*.py # Test files
├── examples/
│ ├── README.md # Example documentation
│ ├── langchain_agent.ipynb # Jupyter notebook tutorial
│ └── langchain_agent.py # CLI agent example
├── pyproject.toml
├── server.json # MCP Registry metadata
├── pytest.ini # (optional) pytest configuration
├── .env.example # (optional) Environment variable template
├── LICENSE # Apache 2.0 license (copy from root)
├── README.md
└── run_tests.sh| Task | File | Pattern |
|---|---|---|
| Add tool | server.py | @mcp.tool() decorator |
| Add resource | server.py | @mcp.resource("uri") decorator |
| Core logic | <core>.py | Async functions, return dicts |
| Test fixtures | tests/conftest.py | @pytest.fixture |
| Unit tests | tests/test_*.py | @pytest.mark.asyncio |
| New server CI | .github/workflows/test.yml | Add lint steps + test job |
| New server CD (PyPI) | .github/workflows/publish-pypi.yml | Add publish job |
| New server CD (MCP) | .github/workflows/publish-mcp-registry.yml | Add publish job |
| MCP Registry metadata | server.json | JSON with name, version, packages |
For comprehensive documentation, read AGENTS.md in the repository root.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.