fix(packaging): move templates into core/ for PyPI distribution

Templates were at project root (templates/) which is outside the Python
package, so `pip install mcphub-server` would not include them. Moved to
core/templates/ and updated path references in server.py and
core/dashboard/routes.py. Also added py-modules for server.py and
server_multi.py to pyproject.toml.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
airano
2026-02-18 02:41:28 +03:30
parent 5e0441c85e
commit 7daf604a32
18 changed files with 16 additions and 9 deletions

View File

@@ -72,7 +72,7 @@ All configured in `pyproject.toml`:
├── server_multi.py # Alternative multi-endpoint server ├── server_multi.py # Alternative multi-endpoint server
├── core/ # Layer 1: Core system modules ├── core/ # Layer 1: Core system modules
├── plugins/ # Layer 2: Plugin system (9 plugins) ├── plugins/ # Layer 2: Plugin system (9 plugins)
├── templates/ # Jinja2 templates (dashboard + OAuth) ├── core/templates/ # Jinja2 templates (dashboard + OAuth)
├── tests/ # Organized test suite ├── tests/ # Organized test suite
├── scripts/ # Setup & deployment scripts ├── scripts/ # Setup & deployment scripts
├── wordpress-plugin/ # Companion WP plugins (PHP) ├── wordpress-plugin/ # Companion WP plugins (PHP)
@@ -181,7 +181,7 @@ Types: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`
- `server_multi.py` is the alternative multi-endpoint entry point; `server.py` is the primary - `server_multi.py` is the alternative multi-endpoint entry point; `server.py` is the primary
- `wordpress-plugin/` contains companion WP plugins (openpanel, seo-api-bridge) — these are PHP, not Python - `wordpress-plugin/` contains companion WP plugins (openpanel, seo-api-bridge) — these are PHP, not Python
- `env.example` has "FUTURE" labels for Supabase/Gitea but both are fully implemented - `env.example` has "FUTURE" labels for Supabase/Gitea but both are fully implemented
- Dashboard templates live in `templates/` (not inside `core/dashboard/`) - Dashboard templates live in `core/templates/` (included in pip package as `package_data`)
- `ruff` config uses top-level `select` key in pyproject.toml (not `[tool.ruff.lint]` nested format) - `ruff` config uses top-level `select` key in pyproject.toml (not `[tool.ruff.lint]` nested format)
- The `scripts/` directory has platform-specific setup scripts: `setup.sh` (Linux/Mac), `setup.ps1` (Windows) - The `scripts/` directory has platform-specific setup scripts: `setup.sh` (Linux/Mac), `setup.ps1` (Windows)

View File

@@ -16,10 +16,8 @@ from .auth import get_dashboard_auth
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# Templates directory # Templates directory (core/templates/ — one level up from core/dashboard/)
TEMPLATES_DIR = os.path.join( TEMPLATES_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), "templates")
os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "templates"
)
templates = Jinja2Templates(directory=TEMPLATES_DIR) templates = Jinja2Templates(directory=TEMPLATES_DIR)
# Plugin display names mapping (for special cases like n8n) # Plugin display names mapping (for special cases like n8n)

View File

@@ -79,7 +79,7 @@
<div class="mt-6 text-center" {% if lang == 'fa' %}dir="rtl"{% endif %}> <div class="mt-6 text-center" {% if lang == 'fa' %}dir="rtl"{% endif %}>
<p class="text-xs text-gray-500 dark:text-gray-400"> <p class="text-xs text-gray-500 dark:text-gray-400">
{{ t.need_help }} {{ t.need_help }}
<a href="https://github.com/airano-ir/mcphub" class="text-purple-600 dark:text-purple-400 hover:underline">{{ t.documentation }}</a> <a href="https://github.com/airano-ir/coolify-mcp-hub" class="text-purple-600 dark:text-purple-400 hover:underline">{{ t.documentation }}</a>
</p> </p>
</div> </div>
</div> </div>

View File

@@ -66,11 +66,15 @@ Changelog = "https://github.com/airano-ir/mcphub/releases"
requires = ["setuptools>=68.0", "wheel"] requires = ["setuptools>=68.0", "wheel"]
build-backend = "setuptools.build_meta" build-backend = "setuptools.build_meta"
[tool.setuptools]
py-modules = ["server", "server_multi"]
[tool.setuptools.packages.find] [tool.setuptools.packages.find]
include = ["core*", "plugins*"] include = ["core*", "plugins*"]
exclude = ["tests*", "data*", "logs*", "temp*", "scripts*", "docs*"] exclude = ["tests*", "data*", "logs*", "temp*", "scripts*", "docs*"]
[tool.setuptools.package-data] [tool.setuptools.package-data]
"core" = ["templates/**/*.html"]
"*" = ["*.html", "*.css", "*.js", "*.json"] "*" = ["*.html", "*.css", "*.js", "*.json"]
# ==================================== # ====================================

View File

@@ -230,8 +230,13 @@ if OAUTH_AUTH_MODE == "trusted_domains":
# Initialize MCP server # Initialize MCP server
mcp = FastMCP("MCP Hub") mcp = FastMCP("MCP Hub")
# Initialize Jinja2 templates (Phase E - OAuth Authorization Page) # Initialize Jinja2 templates
templates = Jinja2Templates(directory="templates") # Templates live in core/templates/ (included in pip package as package_data)
_TEMPLATES_DIR = os.path.join(os.path.dirname(__file__), "core", "templates")
if not os.path.isdir(_TEMPLATES_DIR):
# Fallback for pip-installed package: resolve relative to core package
_TEMPLATES_DIR = os.path.join(os.path.dirname(os.path.abspath(core.__file__)), "templates")
templates = Jinja2Templates(directory=_TEMPLATES_DIR)
logger.info("Jinja2 template engine initialized") logger.info("Jinja2 template engine initialized")
# Initialize managers # Initialize managers