Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
"dockerfile": "Dockerfile",
"context": ".."
},
"features": {},
"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "lts"
}
},
"postCreateCommand": ".devcontainer/postCreateCommand.sh",
"customizations": {
"vscode": {
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,10 @@ uv.lock
certs/
jwt/

# Static assets (downloaded during container build)
# Static assets (downloaded or built during container build)
mcpgateway/static/vendor/
mcpgateway/static/bundle-*.js
mcpgateway/static/.vite/
public/

# Export & SBOM files
Expand Down
32 changes: 16 additions & 16 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"files": "^.secrets.baseline|package-lock.json|Cargo.lock|scripts/sign_image.sh|scripts/zap|sonar-project.properties|uv.lock|^.secrets.baseline$",
"lines": null
},
"generated_at": "2026-04-11T14:12:29Z",
"generated_at": "2026-04-11T14:31:54Z",
"plugins_used": [
{
"name": "AWSKeyDetector"
Expand Down Expand Up @@ -200,39 +200,39 @@
"hashed_secret": "f4793151b0607198d4de9b1ca458d3e25adf1cb7",
"is_secret": false,
"is_verified": false,
"line_number": 111,
"line_number": 112,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "fa9beb99e4029ad5a6615399e7bbae21356086b3",
"is_secret": false,
"is_verified": false,
"line_number": 187,
"line_number": 188,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "7b4455a56fbf1d198e45e04c437488514645a82c",
"is_secret": false,
"is_verified": false,
"line_number": 189,
"line_number": 190,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "90bd1b48e958257948487b90bee080ba5ed00caa",
"is_secret": false,
"is_verified": false,
"line_number": 261,
"line_number": 262,
"type": "Hex High Entropy String",
"verified_result": null
},
{
"hashed_secret": "48ffbad96aa9c2b33f9486f5a3c2108198acb518",
"is_secret": false,
"is_verified": false,
"line_number": 262,
"line_number": 263,
"type": "Hex High Entropy String",
"verified_result": null
}
Expand Down Expand Up @@ -344,79 +344,79 @@
"hashed_secret": "844c398e469ef3fb919da3778944365ab2175fb7",
"is_secret": false,
"is_verified": false,
"line_number": 441,
"line_number": 469,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "319037749ce37e577db0b3628c7f90e333544391",
"is_secret": false,
"is_verified": false,
"line_number": 865,
"line_number": 893,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "6ae2832e494d1098e8901fe156083e39399a24f1",
"is_secret": false,
"is_verified": false,
"line_number": 867,
"line_number": 895,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "43fc45734b96bcb1b6cef373e949eb3524ae199b",
"is_secret": false,
"is_verified": false,
"line_number": 1558,
"line_number": 1586,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "9d989e8d27dc9e0ec3389fc855f142c3d40f0c50",
"is_secret": false,
"is_verified": false,
"line_number": 1769,
"line_number": 1797,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "d3ac7a4ef1a838b4134f2f6e7f3c0d249d74b674",
"is_secret": false,
"is_verified": false,
"line_number": 6113,
"line_number": 6141,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "5932862bcd24dd27d0dc0407ec94fe9d6ea24aeb",
"is_secret": false,
"is_verified": false,
"line_number": 6610,
"line_number": 6638,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "c77c805e32f173e4321ee9187de9c29cb3804513",
"is_secret": false,
"is_verified": false,
"line_number": 6622,
"line_number": 6650,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "8fe3df8a68ddd0d4ab2214186cbb8e38ccd0e06a",
"is_secret": false,
"is_verified": false,
"line_number": 6694,
"line_number": 6722,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "93ac8946882128457cd9e283b30ca851945e6690",
"is_secret": false,
"is_verified": false,
"line_number": 7765,
"line_number": 7793,
"type": "Secret Keyword",
"verified_result": null
}
Expand Down
3 changes: 2 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@ llms/ # End-user LLM guidance (not for code agents)
```bash
cp .env.example .env && make install-dev check-env # Complete setup
make venv # Create virtual environment with uv
make install-dev # Install with dev dependencies
make install-dev # Install with dev dependencies (includes build-ui)
make check-env # Verify .env against .env.example
make build-ui # Rebuild Admin UI JS bundle (requires npm)
```

### Development
Expand Down
28 changes: 28 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,34 @@ install-db: venv
.PHONY: install-dev
install-dev: venv
@/bin/bash -c "source $(VENV_DIR)/bin/activate && $(UV_BIN) pip install --group dev '.[plugins]'"
@if [ "$(ENABLE_RUST_BUILD)" = "1" ]; then \
echo "πŸ¦€ Building Rust plugins..."; \
$(MAKE) rust-dev || echo "⚠️ Rust plugins not available (optional)"; \
else \
echo "⏭️ Rust builds disabled (set ENABLE_RUST_BUILD=1 to enable)"; \
fi
@$(MAKE) build-ui

# help: build-ui - Build Admin UI JS bundle with Vite (requires npm; set SKIP_UI_BUILD=1 to bypass)
.PHONY: build-ui
build-ui:
@if [ "$(SKIP_UI_BUILD)" = "1" ]; then \
echo "⏭️ SKIP_UI_BUILD=1 β€” skipping Admin UI build (the Admin UI will not load at runtime)"; \
elif command -v npm >/dev/null 2>&1; then \
echo "πŸ”¨ Building Admin UI bundle..."; \
if [ -f package-lock.json ]; then \
npm ci --no-audit --no-fund; \
else \
echo "ℹ️ package-lock.json not found β€” falling back to 'npm install'"; \
npm install --no-audit --no-fund; \
fi && \
npm run vite:build; \
else \
echo "❌ npm not found β€” install Node.js (https://nodejs.org) to build the Admin UI."; \
echo " Without the bundle, /admin will fail to load at runtime."; \
echo " To bypass this step intentionally, re-run with SKIP_UI_BUILD=1."; \
exit 1; \
fi

.PHONY: update
update:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,7 @@ For detailed setup, workflows, and GitHub Codespaces instructions, see **[Develo
## Installation

```bash
make venv install # create .venv + install deps
make venv install-dev # create .venv + install deps + build Admin UI
make serve # gunicorn on :4444
```

Expand Down
31 changes: 31 additions & 0 deletions docs/docs/development/building.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,37 @@ The Admin UI uses plain JavaScript (not TypeScript). Frontend tooling requires N
npm install # install frontend dev dependencies
```

### Building the Admin UI Bundle

The Admin UI JavaScript is bundled with Vite. The bundle is **not committed** to the repository β€” it must be built locally. `make install-dev` invokes `make build-ui` automatically, and the step is required: without a bundle, `/admin` will fail to load at runtime with `No bundle-*.js found`. Rebuild after any changes to files under `mcpgateway/admin_ui/`.

**Node.js is a prerequisite.** If `npm` is missing, `make build-ui` (and therefore `make install-dev`) fails fast rather than leaving a broken install. Install Node.js from <https://nodejs.org> before running setup.

```bash
make build-ui # build mcpgateway/static/bundle-<hash>.js (requires npm)
```

If you genuinely do not need the Admin UI (for example, a headless API-only deployment where `MCPGATEWAY_UI_ENABLED=false`), bypass the step with:

```bash
SKIP_UI_BUILD=1 make install-dev
```

Or build manually:

```bash
npm ci # install dependencies from lockfile (falls back to `npm install` if lockfile absent)
npm run vite:build # produce mcpgateway/static/bundle-<hash>.js
```

The server reads `mcpgateway/static/.vite/manifest.json` at startup to locate the hashed bundle filename.

For iterative development you can use watch mode:

```bash
npx vite build --watch
```

### Linting & Formatting

```bash
Expand Down
4 changes: 4 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
const neostandard = require("neostandard");

module.exports = [
// Ignore compiled build artefacts β€” these are minified and not authored code
{
ignores: ["mcpgateway/static/bundle-*.js", "mcpgateway/static/.vite/**"],
},
...neostandard({
env: ["browser"],
ignores: neostandard.resolveIgnoresFromGitignore(),
Expand Down
Loading