Skip to content

chore: build with hatchling only and move MCP deps to an extra - #45

Open
SkyeAv wants to merge 1 commit into
mainfrom
feat/solidify-hatchling-build-system-with-extras
Open

chore: build with hatchling only and move MCP deps to an extra#45
SkyeAv wants to merge 1 commit into
mainfrom
feat/solidify-hatchling-build-system-with-extras

Conversation

@SkyeAv

@SkyeAv SkyeAv commented Jul 27, 2026

Copy link
Copy Markdown
Member

Consolidates the project on a single hatchling build via pyproject.toml and moves the MCP server dependencies into an optional mcp extra, so a base install of TCT no longer pulls in the MCP stack.

Build system

  • Single backend: deletes the legacy setup.py (setuptools) and the stale root requirements.txt; pyproject.toml (hatchling) is now the only build source of truth. setup.py had drifted to 0.1.6 and even listed the stdlib copy module as a dependency.
  • Wheel unchanged: reuses the existing [tool.hatch.build.targets.wheel] packages = ["TCT"]; the wheel still ships exactly the TCT/ modules.

MCP extra

  • New extra: adds [project.optional-dependencies] mcp = ["fastmcp>=2.12.2", "click>=8.2.1"] and removes both from the required dependencies.
  • Clean split: only TCT/server.py imports fastmcp/mcp, and TCT/__init__.py never imports the server, so the core package imports fine without the extra.
  • click included: it was only present to satisfy fastmcp and isn't imported anywhere in TCT/, so it moves into the extra too.

Dev/CI ergonomics

  • Makefile: install now runs uv sync --all-extras --dev, matching .github/workflows/main.yml, so local dev installs the mcp extra and tests/test_server.py runs.
  • Test guard: tests/test_server.py now starts with pytest.importorskip("fastmcp"), so a no-extras install skips the module instead of erroring at collection.
  • Lock: uv.lock regenerated; this also corrected the locked project version from the stale 0.1.6 to 0.2.0.

Design

  • Why an extra: the MCP server is a thin wrapper over the core toolkit; an optional extra keeps one distribution while letting non-MCP consumers avoid fastmcp/mcp and their transitive deps.
  • Deferred: the pre-existing tct-server = "main:main" console script points at root main.py, which the hatchling wheel (packages = ["TCT"]) does not ship — so the installed script won't resolve. Left out of scope; worth a follow-up to move the entrypoint to TCT.server:main.
  • Accepted caveat: TCT/.ipynb_checkpoints/ is git-tracked (Jupyter autosave) and was not touched here.

Testing

  • uv buildSuccessfully built dist/tct-0.2.0.tar.gz and dist/tct-0.2.0-py3-none-any.whl.
  • unzip -p dist/tct-*.whl tct-0.2.0.dist-info/METADATAProvides-Extra: mcp, Requires-Dist: fastmcp>=2.12.2; extra == 'mcp', Requires-Dist: click>=8.2.1; extra == 'mcp'.
  • Fresh venv, base wheel → import TCT OK; fastmcp installed? False.
  • Fresh venv, wheel[mcp]import TCT.server OK; fastmcp/click present; mcp.name == "translator-toolkit".
  • uv sync --all-extras --dev && uv run pytest tests/test_server.py -v --no-cov3 passed.
  • No-fastmcp venv, pytest tests/test_server.py1 skipped (could not import 'fastmcp').
  • uv run ruff check tests/test_server.pyAll checks passed! (the 19 repo-wide ruff errors are pre-existing in TCT/ sources, untouched here; CI runs ruff with continue-on-error).

Questions for the reviewer

  • tct-server script. Fix the broken console script (move the entrypoint to TCT.server:main) in a follow-up, or fold it into this PR?

Drop the legacy setuptools build (setup.py) and the stale root
requirements.txt; pyproject.toml (hatchling) is now the single build
source of truth.

Move the MCP server dependencies (fastmcp, click) out of the required
dependency list into an optional 'mcp' extra, so a base install of TCT
no longer pulls in the MCP stack. The core package never imported the
server at import time, so this is a clean split.

- pyproject.toml: add [project.optional-dependencies] mcp; remove
  fastmcp/click from required deps.
- Makefile: install now runs 'uv sync --all-extras --dev' (matches CI).
- tests/test_server.py: pytest.importorskip("fastmcp") so the suite
  skips cleanly when the extra is absent.
- uv.lock: regenerated (also bumps the locked version 0.1.6 -> 0.2.0).
@SkyeAv
SkyeAv requested a review from yjzhang July 27, 2026 21:07
@SkyeAv SkyeAv self-assigned this Jul 27, 2026
@SkyeAv SkyeAv added enhancement New feature or request question Further information is requested labels Jul 27, 2026
@SkyeAv

SkyeAv commented Jul 27, 2026

Copy link
Copy Markdown
Member Author

Should I rerun tests if they're failing because node norm and such seem to be down?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request question Further information is requested

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant