From 3f38f470e91df658bc12a55601aa111abd5d5305 Mon Sep 17 00:00:00 2001 From: Mihai Criveti Date: Tue, 27 May 2025 09:30:45 +0100 Subject: [PATCH] Update Makefile and pyproject.toml with packaging steps --- CHANGELOG.md | 0 MANIFEST.in | 50 ++++++++++++++++ Makefile | 35 +++++++++++ SECURITY.md | 0 mcpgateway/py.typed | 0 pyproject.toml | 140 +++++++++++++++++++++++++++++++------------- 6 files changed, 185 insertions(+), 40 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 MANIFEST.in create mode 100644 SECURITY.md create mode 100644 mcpgateway/py.typed diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..e69de29bb diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 000000000..be58c4ca2 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,50 @@ +# ────────────────────────────────────────────────────────────── +# MANIFEST.in – source-distribution contents for mcpgateway +# ────────────────────────────────────────────────────────────── + +# 1️⃣ Core project files that SDists/Wheels should always carry +include LICENSE +include README.md +include pyproject.toml +include gunicorn.config.py +include Containerfile +include Containerfile.lite + +# 2️⃣ Top-level config, examples and helper scripts +include *.py +include *.md +include *.example +include *.lock +include *.properties +include *.toml +include *.yaml +include *.yml +include *.json +include *.sh +include *.txt + +# 3️⃣ Tooling/lint configuration dot-files (explicit so they're not lost) +include .darglint +include .dockerignore +include .flake8 +include .htmlhintrc +include .pycodestyle +include .pylintrc +include .whitesource +include .coveragerc +#include .gitignore # purely optional but many projects ship it + +# 4️⃣ Runtime data that lives *inside* the package at import time +recursive-include mcpgateway/templates *.html +recursive-include mcpgateway/static *.css *.js *.gif *.png *.svg +recursive-include mcpgateway *.pyi py.typed + +# 5️⃣ (Optional) include MKDocs-based docs in the sdist +graft docs + +# 6️⃣ Never publish caches, compiled or build outputs +global-exclude __pycache__ *.py[cod] *.so *.dylib +prune build +prune dist +prune .eggs +prune *.egg-info diff --git a/Makefile b/Makefile index 4b0c2b7ee..03438a03b 100644 --- a/Makefile +++ b/Makefile @@ -688,6 +688,41 @@ containerfile-update: @sed -i.bak -E 's|^(FROM\s+\S+):[^\s]+|\1:latest|' Containerfile && rm -f Containerfile.bak @echo "✅ Base image updated to latest." + +# ============================================================================= +# 📦 PACKAGING & PUBLISHING +# ============================================================================= +# help: 📦 PACKAGING & PUBLISHING +# help: dist - Clean-build wheel *and* sdist into ./dist +# help: wheel - Build wheel only +# help: sdist - Build source distribution only +# help: verify - Build + twine + check-manifest + pyroma (no upload) +# help: publish - Verify, then upload to PyPI (needs TWINE_* creds) +# ============================================================================= +.PHONY: dist wheel sdist verify publish + +dist: clean ## Build wheel + sdist + python -m build + @echo "🛠 Wheel & sdist written to ./dist" + +wheel: ## Build wheel only + python -m build -w + @echo "🛠 Wheel written to ./dist" + +sdist: ## Build source distribution only + python -m build -s + @echo "🛠 Source distribution written to ./dist" + +verify: dist ## Build, run metadata & manifest checks + twine check dist/* # metadata sanity + check-manifest # sdist completeness + pyroma -d . # metadata quality score + @echo "✅ Package verified – ready to publish." + +publish: verify ## Verify, then upload to PyPI + twine upload dist/* # creds via env vars or ~/.pypirc + @echo "🚀 Upload finished – check https://pypi.org/project/$(PROJECT_NAME)/" + # ============================================================================= # 🦭 PODMAN CONTAINER BUILD & RUN # ============================================================================= diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..e69de29bb diff --git a/mcpgateway/py.typed b/mcpgateway/py.typed new file mode 100644 index 000000000..e69de29bb diff --git a/pyproject.toml b/pyproject.toml index 338eb1019..799dcc4f7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,16 +1,23 @@ +# ---------------------------------------------------------------- +# 💡 Build system (PEP 517) +# • setuptools ≥ 77 gives SPDX licence support (PEP 639) +# • wheel is needed by most build front-ends +# ---------------------------------------------------------------- [build-system] -requires = [ "setuptools>=42", "wheel",] +requires = ["setuptools>=77", "wheel"] build-backend = "setuptools.build_meta" +# ---------------------------------------------------------------- +# 📦 Core project metadata (PEP 621) +# ---------------------------------------------------------------- [project] name = "mcpgateway" -version = "1.0.0" -description = "A production-ready MCP Gateway built with FastAPI and the official MCP Python SDK" +version = "0.1.0" +description = "A production-ready MCP Gateway built with FastAPI and support for virtual servers" keywords = ["MCP", "Gateway", "API", "Agents", "Tools"] classifiers = [ - "Development Status :: 3 - Alpha", + "Development Status :: 4 - Beta", "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -18,7 +25,20 @@ classifiers = [ "Framework :: FastAPI", ] readme = "README.md" -requires-python = ">=3.10" +requires-python = ">=3.10,<3.13" + +# SPDX licence expression + explicit licence file (PEP 639) +license = "Apache-2.0" +license-files = ["LICENSE"] + +# Maintainers +maintainers = [ + {name = "Mihai Criveti", email = "redacted@ibm.com"} +] + +# ---------------------------------------------------------------- +# Runtime dependencies +# ---------------------------------------------------------------- dependencies = [ "cryptography>=45.0.3", "fastapi>=0.115.12", @@ -39,14 +59,18 @@ dependencies = [ "uvicorn>=0.34.2", "zeroconf>=0.147.0", ] -[[project.authors]] -name = "Mihai Criveti" -email = "redacted@ibm.com" - -[project.license] -text = "Apache License 2.0" +# ---------------------------------------------------------------- +# Optional dependency groups (extras) +# ---------------------------------------------------------------- [project.optional-dependencies] + +# Optional dependency groups (runtime) +redis = [ + "redis>=6.1.0", +] + +# Optional dependency groups (development) dev = [ "argparse-manpage>=4.6", "autoflake>=2.3.1", @@ -84,26 +108,75 @@ dev = [ "pytest-rerunfailures>=15.1", "pytest-xdist>=3.6.1", "pytype>=2024.10.11", - "pytype>=2024.10.11", "radon>=6.0.1", "ruff>=0.11.11", "settings-doc>=4.3.2", "snakeviz>=2.2.2", "ty>=0.0.1a6", + "twine>=6.1.0", "types-tabulate>=0.9.0.20241207", ] -redis = [ - "redis>=6.1.0", -] + +# Convenience meta-extras +all = ["mcpgateway[redis]"] +dev-all = ["mcpgateway[redis,dev]"] + +# -------------------------------------------------------------------- +# Authors and URLs +# -------------------------------------------------------------------- +[[project.authors]] +name = "Mihai Criveti" +email = "redacted@ibm.com" [project.urls] -Homepage = "https://github.com/IBM/mcp-context-forge" -Documentation = "https://github.com/IBM/mcp-context-forge/docs" -Source = "https://github.com/IBM/mcp-context-forge" +Homepage = "https://ibm.github.io/mcp-context-forge/" +Documentation = "https://ibm.github.io/mcp-context-forge/" +Repository = "https://github.com/IBM/mcp-context-forge" +"Bug Tracker" = "https://github.com/IBM/mcp-context-forge/issues" +Changelog = "https://github.com/IBM/mcp-context-forge/blob/main/CHANGELOG.md" + +# -------------------------------------------------------------------- +# 🔧 setuptools-specific configuration +# -------------------------------------------------------------------- +[tool.setuptools] +include-package-data = true # ensure wheels include the data files + +# Automatic discovery: keep every package that starts with "mcpgateway" +[tool.setuptools.packages.find] +include = ["mcpgateway*"] +exclude = ["tests*"] + +## Runtime data files ------------------------------------------------ +# - py.typed -> advertises inline type hints (PEP 561) +# - static/* -> CSS/JS for the admin UI +# - templates -> Jinja2 templates shipped at runtime +[tool.setuptools.package-data] +mcpgateway = [ + "py.typed", + "static/*.css", + "static/*.js", + "templates/*.html" +] + +# -------------------------------------------------------------------- +# 🛠 Tool configurations (black, mypy, etc.) +# -------------------------------------------------------------------- +[tool.pytype] +# Directory-specific options: +inputs = ["mcpgateway"] +python_version = "3.11" # match default runtime + +[tool.check-manifest] +ignore = [ + "docs/**", + "tests/**", + ".github/**", + "Makefile", +] [tool.black] line-length = 200 -target-version = [ "py310",] +target-version = ["py310", "py311", "py312"] include = "\\.pyi?$" [tool.isort] @@ -115,6 +188,9 @@ python_version = "3.10" warn_return_any = true warn_unused_configs = true disallow_untyped_defs = true +strict = true +show_error_codes = true +warn_unreachable = true [tool.pytest.ini_options] minversion = "6.0" @@ -122,29 +198,12 @@ addopts = "-ra -q --cov=mcpgateway" testpaths = [ "tests",] asyncio_mode = "auto" -[tool.setuptools.packages.find] -where = [ ".",] -include = [ "mcpgateway*",] - -[tool.pytype] -# Directory-specific options: -inputs = ["mcpgateway"] -python_version = "3.11" # match your default runtime - -[tool.check-manifest] -# Usually you only need 'ignore', but other flags are available. -ignore = [ - "docs/**", - "tests/**", - ".github/**", - "Makefile", -] - +# ── fawltydeps ───────────────────────────────────────────────────── [tool.fawltydeps] -# only parse your main pyproject.toml +# only parse main pyproject.toml deps = ["pyproject.toml"] -# ignore all of your 'dev' extras so they won't show up +# ignore 'dev' extras so they won't show up in fawltydeps ignore_unused = [ "autoflake", "argparse-manpage", @@ -189,5 +248,6 @@ ignore_unused = [ "settings-doc", "snakeviz", "types-tabulate", + "twine", "uvicorn" ]