diff --git a/.github/workflows/publish-openbb-mcp-server.yml b/.github/workflows/publish-openbb-mcp-server.yml index 4d7d88ebae5..a98bb95d995 100644 --- a/.github/workflows/publish-openbb-mcp-server.yml +++ b/.github/workflows/publish-openbb-mcp-server.yml @@ -141,7 +141,7 @@ jobs: - name: Install dependencies then openbb-mcp-server wheel run: | uv pip install --system ../../core - uv pip install --system --no-sources ../../../cli tests/fixtures/openbb_mcp_fixture + uv pip install --system --no-sources ../../../cli uv pip install --system --no-sources --group dev uv pip install --system --no-sources dist/openbb_mcp_server-*.whl diff --git a/.github/workflows/test-unit-mcp-server.yml b/.github/workflows/test-unit-mcp-server.yml index fae086aad53..42550f0c387 100644 --- a/.github/workflows/test-unit-mcp-server.yml +++ b/.github/workflows/test-unit-mcp-server.yml @@ -71,7 +71,7 @@ jobs: - name: Install dependencies then openbb-mcp-server wheel run: | uv pip install --system ../../core - uv pip install --system --no-sources ../../../cli tests/fixtures/openbb_mcp_fixture + uv pip install --system --no-sources ../../../cli uv pip install --system --no-sources --group dev uv pip install --system --no-sources dist/openbb_mcp_server-*.whl @@ -123,7 +123,7 @@ jobs: - name: Install dependencies then openbb-mcp-server wheel run: | uv pip install --system ../../core - uv pip install --system --no-sources ../../../cli tests/fixtures/openbb_mcp_fixture + uv pip install --system --no-sources ../../../cli uv pip install --system --no-sources --group dev uv pip install --system --no-sources dist/openbb_mcp_server-*.whl diff --git a/cli/conftest.py b/cli/conftest.py index 74634566d80..5f78ff3ba35 100644 --- a/cli/conftest.py +++ b/cli/conftest.py @@ -31,16 +31,7 @@ from pathlib import Path import pytest - -def _installed_openbb_dir() -> Path: - """Return the directory of the ``openbb`` package this interpreter imports.""" - spec = importlib.util.find_spec("openbb") - if spec is None or not spec.submodule_search_locations: - raise RuntimeError("The `openbb` package is not installed in this interpreter.") - return Path(next(iter(spec.submodule_search_locations))) - - -OPENBB_DIR = _installed_openbb_dir() +OPENBB_DIR = Path(importlib.util.find_spec("openbb").origin).parent PACKAGE_DIR = OPENBB_DIR / "package" ASSETS_DIR = OPENBB_DIR / "assets" diff --git a/openbb_platform/extensions/mcp_server/pyproject.toml b/openbb_platform/extensions/mcp_server/pyproject.toml index 738cbf1d888..971c62cfda2 100644 --- a/openbb_platform/extensions/mcp_server/pyproject.toml +++ b/openbb_platform/extensions/mcp_server/pyproject.toml @@ -27,9 +27,7 @@ Documentation = "https://docs.openbb.co/odp/python/extensions/interface/openbb-m [dependency-groups] dev = [ "openbb-devtools>=2.0.1", - "httpx>=0.28.0,<1.0.0", "openbb-cli>=2.0.0", - "openbb-mcp-fixture", ] [build-system] @@ -46,10 +44,6 @@ include = [ "pyproject.toml", ] -[tool.uv.sources] -openbb-cli = { path = "../../../cli", editable = true } -openbb-mcp-fixture = { path = "tests/fixtures/openbb_mcp_fixture", editable = true } - [tool.ruff] line-length = 88 target-version = "py310" diff --git a/openbb_platform/extensions/mcp_server/tests/conftest.py b/openbb_platform/extensions/mcp_server/tests/conftest.py index e4efec13f4f..bc58e52979d 100644 --- a/openbb_platform/extensions/mcp_server/tests/conftest.py +++ b/openbb_platform/extensions/mcp_server/tests/conftest.py @@ -1,68 +1,43 @@ """Shared fixtures and ``openbb_core`` submodule bindings for the test suite.""" +import atexit import importlib import logging import shutil import socket -import subprocess import sys +import tempfile import threading import time from collections.abc import Iterator from contextlib import contextmanager -from importlib.metadata import PackageNotFoundError, distribution -from importlib.util import find_spec from pathlib import Path -FIXTURE_EXTENSION = Path(__file__).parent / "fixtures" / "openbb_mcp_fixture" +FIXTURES_DIR = Path(__file__).parent / "fixtures" -def _pip_install_command() -> list[str]: - """Return the command that installs packages into the running interpreter. +def _register_fixture_extension() -> None: + """Expose ``openbb_mcp_fixture.router`` as an ``openbb_core_extension`` entry point.""" + metadata_root = Path(tempfile.mkdtemp(prefix="openbb_mcp_fixture_")) + atexit.register(shutil.rmtree, metadata_root, ignore_errors=True) + dist_info = metadata_root / "openbb_mcp_fixture-0.0.0.dist-info" + dist_info.mkdir() + (dist_info / "METADATA").write_text( + "Metadata-Version: 2.1\nName: openbb-mcp-fixture\nVersion: 0.0.0\n", + encoding="utf-8", + ) + (dist_info / "entry_points.txt").write_text( + "[openbb_core_extension]\nmcp_fixture = openbb_mcp_fixture.router:router\n", + encoding="utf-8", + ) + sys.path[:0] = [str(FIXTURES_DIR), str(metadata_root)] + importlib.invalidate_caches() + from openbb_core.app.extension_loader import ExtensionLoader - Returns - ------- - list[str] - ``uv pip install`` when uv is available, otherwise ``pip install``. - """ - if find_spec("uv"): - return [ - sys.executable, - "-m", - "uv", - "pip", - "install", - "--python", - sys.executable, - ] - if uv := shutil.which("uv"): - return [uv, "pip", "install", "--python", sys.executable] - return [sys.executable, "-m", "pip", "install"] + type(ExtensionLoader)._instances.pop(ExtensionLoader, None) -def _install_fixture_extension() -> None: - """Install the ``openbb-mcp-fixture`` extension the tests dispatch against.""" - try: - distribution("openbb-mcp-fixture") - except PackageNotFoundError: - subprocess.run( # noqa: S603 - [ - *_pip_install_command(), - "--no-deps", - "--editable", - str(FIXTURE_EXTENSION), - ], - check=True, - ) - if str(FIXTURE_EXTENSION) not in sys.path: - sys.path.append(str(FIXTURE_EXTENSION)) - importlib.invalidate_caches() - from openbb_core.app.extension_loader import ExtensionLoader - - type(ExtensionLoader)._instances.pop(ExtensionLoader, None) - - -_install_fixture_extension() +_register_fixture_extension() import openbb_core.api import openbb_core.api.app_loader @@ -146,10 +121,10 @@ def serve_app(app) -> Iterator[str]: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(("127.0.0.1", 0)) port = sock.getsockname()[1] - server = uvicorn.Server(uvicorn.Config(app, log_level="warning")) + server = uvicorn.Server(uvicorn.Config(app, log_level="warning", ws="none")) thread = threading.Thread(target=server.run, kwargs={"sockets": [sock]}) thread.start() - while not server.started: + while thread.is_alive() and not server.started: time.sleep(0.01) try: yield f"http://127.0.0.1:{port}" diff --git a/openbb_platform/extensions/mcp_server/tests/fixtures/openbb_mcp_fixture/openbb_mcp_fixture/__init__.py b/openbb_platform/extensions/mcp_server/tests/fixtures/openbb_mcp_fixture/__init__.py similarity index 100% rename from openbb_platform/extensions/mcp_server/tests/fixtures/openbb_mcp_fixture/openbb_mcp_fixture/__init__.py rename to openbb_platform/extensions/mcp_server/tests/fixtures/openbb_mcp_fixture/__init__.py diff --git a/openbb_platform/extensions/mcp_server/tests/fixtures/openbb_mcp_fixture/pyproject.toml b/openbb_platform/extensions/mcp_server/tests/fixtures/openbb_mcp_fixture/pyproject.toml deleted file mode 100644 index 5eac7ffe1f0..00000000000 --- a/openbb_platform/extensions/mcp_server/tests/fixtures/openbb_mcp_fixture/pyproject.toml +++ /dev/null @@ -1,18 +0,0 @@ -[project] -name = "openbb-mcp-fixture" -version = "0.0.1" -description = "Deterministic OpenBB extension that the openbb-mcp-server tests dispatch against." -authors = [{ name = "OpenBB Team", email = "hello@openbb.co" }] -license = { text = "Apache-2.0" } -requires-python = ">=3.10,<4" -dependencies = ["openbb-core>=2.0.0"] - -[project.entry-points."openbb_core_extension"] -mcp_fixture = "openbb_mcp_fixture.router:router" - -[build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" - -[tool.hatch.build.targets.wheel] -packages = ["openbb_mcp_fixture"] diff --git a/openbb_platform/extensions/mcp_server/tests/fixtures/openbb_mcp_fixture/openbb_mcp_fixture/router.py b/openbb_platform/extensions/mcp_server/tests/fixtures/openbb_mcp_fixture/router.py similarity index 100% rename from openbb_platform/extensions/mcp_server/tests/fixtures/openbb_mcp_fixture/openbb_mcp_fixture/router.py rename to openbb_platform/extensions/mcp_server/tests/fixtures/openbb_mcp_fixture/router.py diff --git a/openbb_platform/extensions/mcp_server/uv.lock b/openbb_platform/extensions/mcp_server/uv.lock index ab30219e071..8fb2a92f6a7 100644 --- a/openbb_platform/extensions/mcp_server/uv.lock +++ b/openbb_platform/extensions/mcp_server/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 3 +revision = 2 requires-python = ">=3.10, <4" resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'win32'", @@ -2222,7 +2222,7 @@ wheels = [ [[package]] name = "openbb-cli" version = "2.0.0" -source = { editable = "../../../cli" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, { name = "openbb-core", extra = ["pandas"] }, @@ -2233,26 +2233,10 @@ dependencies = [ { name = "rich" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] - -[package.metadata] -requires-dist = [ - { name = "httpx", specifier = ">=0.28.0,<1.0.0" }, - { name = "openbb-charting", marker = "extra == 'all'", editable = "../../obbject_extensions/charting" }, - { name = "openbb-charting", marker = "extra == 'charting'", editable = "../../obbject_extensions/charting" }, - { name = "openbb-core", extras = ["pandas"], specifier = ">=2.0.0" }, - { name = "openpyxl", specifier = ">=3.1.5,<4.0.0" }, - { name = "prompt-toolkit", specifier = ">=3.0.50,<4.0.0" }, - { name = "python-dotenv", specifier = ">=1.0.1,<2.0.0" }, - { name = "pywry", marker = "extra == 'all'", specifier = ">=2.0.0" }, - { name = "pywry", marker = "extra == 'interactive'", specifier = ">=2.0.0" }, - { name = "pyyaml", specifier = ">=6.0" }, - { name = "rich", specifier = ">=14.0.0,<15.0.0" }, - { name = "tomli", marker = "python_full_version < '3.11'", specifier = ">=2.0" }, +sdist = { url = "https://files.pythonhosted.org/packages/93/01/043189ce5bf7c782f674b02baec0da4bfa445305a731a774523779bb9150/openbb_cli-2.0.0.tar.gz", hash = "sha256:6694e898228502ac0f1a9d28088da0eec9a01efed6660d877801b54f9b48e5de", size = 371511, upload-time = "2026-09-27T21:25:32.68Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/09/a0/efb5eaaaaf6e5ab2d691209ad120a915737ebfefb554a89e364573be94d8/openbb_cli-2.0.0-py3-none-any.whl", hash = "sha256:fa2a0681948f3206b60da6a290d1cac1c687584bf64e4a467bd920186a231e19", size = 406321, upload-time = "2026-09-27T21:25:30.981Z" }, ] -provides-extras = ["charting", "interactive", "all"] - -[package.metadata.requires-dev] -dev = [{ name = "openbb-devtools", specifier = ">=2.0.1" }] [[package]] name = "openbb-core" @@ -2314,17 +2298,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/34/41/e1ad4ea518f756a0a330a72f3df29a0b692c0cff25a7202f0ab36689f75e/openbb_devtools-2.0.1-py3-none-any.whl", hash = "sha256:ff3d96622f7ecaaf37cf2b898f32ecd69234e58f0ca162043e8e2b9bb608517c", size = 1665, upload-time = "2026-09-24T21:51:04.637Z" }, ] -[[package]] -name = "openbb-mcp-fixture" -version = "0.0.1" -source = { editable = "tests/fixtures/openbb_mcp_fixture" } -dependencies = [ - { name = "openbb-core" }, -] - -[package.metadata] -requires-dist = [{ name = "openbb-core", specifier = ">=2.0.0" }] - [[package]] name = "openbb-mcp-server" version = "2.0.0" @@ -2343,17 +2316,15 @@ cli = [ [package.dev-dependencies] dev = [ - { name = "httpx" }, { name = "openbb-cli" }, { name = "openbb-devtools" }, - { name = "openbb-mcp-fixture" }, ] [package.metadata] requires-dist = [ { name = "fastapi", specifier = ">=0.138.2" }, { name = "fastmcp", specifier = ">=4.0.9" }, - { name = "openbb-cli", marker = "extra == 'cli'", editable = "../../../cli" }, + { name = "openbb-cli", marker = "extra == 'cli'", specifier = ">=2.0.0" }, { name = "openbb-core", specifier = ">=2.0.0" }, { name = "tomli", marker = "python_full_version < '3.11'", specifier = ">=2.0" }, ] @@ -2361,10 +2332,8 @@ provides-extras = ["cli"] [package.metadata.requires-dev] dev = [ - { name = "httpx", specifier = ">=0.28.0,<1.0.0" }, - { name = "openbb-cli", editable = "../../../cli" }, + { name = "openbb-cli", specifier = ">=2.0.0" }, { name = "openbb-devtools", specifier = ">=2.0.1" }, - { name = "openbb-mcp-fixture", editable = "tests/fixtures/openbb_mcp_fixture" }, ] [[package]]