Source code for qdk_chemistry.ui._mcp

"""Optional MCP server integration for the QDK Chemistry UI."""

# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See LICENSE.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

from __future__ import annotations

import importlib.util
from typing import Any

from qdk_chemistry import __version__

MCP_INSTALL_MESSAGE = "QDK Chemistry MCP support is not installed. Install 'qdk-chemistry[mcp]' to use qcmcp."
MCP_AVAILABLE = importlib.util.find_spec("mcp") is not None


class _InactiveMCPServer:
    """Preserve shared CLI functions without registering MCP tools."""

    def tool(self, *args: Any, **kwargs: Any):
        """Return an identity decorator matching ``MCPServer.tool``."""
        if len(args) == 1 and callable(args[0]) and not kwargs:
            return args[0]

        def decorator(function):
            return function

        return decorator


if MCP_AVAILABLE:
    from mcp.server.mcpserver import Context as MCPContext
    from mcp.server.mcpserver import MCPServer

    app: Any = MCPServer(
        "qdk-chemistry",
        version=__version__,
        dependencies=["qdk_chemistry"],
        instructions=(
            "Call bind_workspace before every other QDK Chemistry tool when it is available. "
            "Plugin-launched servers require one immutable absolute workspace binding. "
            "Tool descriptions are compact call contracts; before chaining tools or choosing methods and settings, "
            "load the qdk-chemistry-mcp skill when it is available."
        ),
    )
else:
    MCPContext = Any
    app = _InactiveMCPServer()


[docs] def require_mcp() -> None: """Raise an actionable error when MCP support is unavailable.""" if not MCP_AVAILABLE: raise ModuleNotFoundError(MCP_INSTALL_MESSAGE)