Skip to content

Releases: ni-c/mcp-hub

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 13 Aug 23:13
v0.5.0
00e05e2

Changed

  • Breaking: access tokens are bound to one resource by default.
    RESOURCE_BOUND_TOKENS no longer has to be switched on; RFC 8707 binding is
    what you get without asking, and the setting only exists to turn it off.
    A token issued for /paperless/mcp reaches neither another server nor /hub,
    and an authorization request that names no resource is refused with
    invalid_target.

    Upgrading: tokens issued before this release carry no resource and stop
    working, so every connector authorizes once more. To postpone that, set
    RESOURCE_BOUND_TOKENS=false — it restores the old behaviour and logs a
    warning on every start. The default also applies to createHub() for
    programmatic use.

  • Breaking: /health requires a token for /hub. It reports the same
    fleet-wide view as the aggregate — every server's name, state and tool count —
    so a token bound to a single server no longer reads it. Unauthenticated
    liveness monitoring belongs on /livez, unchanged.

  • The uv layer is pinned to a version tag (0.12.3) instead of latest. The
    digest is unchanged, so the image content is identical; upgrades now arrive as
    readable version bumps rather than opaque digest churn.

  • The documentation site builds with VitePress 2. VitePress 1 pins Vite 5,
    which is end-of-life and carries unfixable dev-server advisories; Vite 8 clears
    them. Documentation tooling is not part of the published package or image.

Added

  • Documentation site at mcp-hub.ni-c.de — guides for
    configuration, deployment, clients and security, an architecture walkthrough,
    a troubleshooting FAQ and a full endpoint/meta-tool reference. Built with
    VitePress from docs/, which carries its own manifest so the runtime image
    and the test matrix are unaffected, and published to gh-pages by
    .github/workflows/docs.yml.

v0.4.0

Choose a tag to compare

@github-actions github-actions released this 13 Aug 20:35
v0.4.0
aa419ab

Added

  • Published on npm as @ni-c/mcp-hub
    (the unscoped name belongs to an unrelated project). npx @ni-c/mcp-hub
    starts the hub, mcp-hub-admin ships as a second binary; Docker remains the
    recommended deployment. Releases are published via npm Trusted Publishing
    (OIDC, with provenance) from the new release.yml, which also creates the
    GitHub release from this changelog.

Changed

  • The version reported by the /hub server and the child MCP clients is now
    read from package.json instead of being hardcoded in two source files.
  • zod updated to v4, the runtime image moved to node:26-bookworm-slim, and
    all GitHub Actions moved to their current majors (checkout v7, setup-node v7,
    CodeQL v4, docker/* v4/v6/v7, trivy-action 0.36).

Fixed

  • The mcp-hub binary was missing its shebang line, so the npm-installed
    command would not execute on Unix.

v0.3.0

Choose a tag to compare

@ni-c ni-c released this 13 Aug 18:49
v0.3.0
ed017f2

Security-hardening release. Every change comes from an internal security audit of the hub; the full deployment guidance now lives in SECURITY.md.

Security

  • Resource-bound tokens (RFC 8707): a client that sends a resource indicator receives an access token bound to /hub or one /<name>/mcp — usable nowhere else on the hub. The login/consent pages display the requested resource, and the code/refresh exchanges verify it. Set RESOURCE_BOUND_TOKENS=true to make the indicator mandatory for every new token (recommended; legacy global tokens then stop working and clients re-authorize once).
  • Access tokens now expire after 15 minutes (down from 24 hours); refresh tokens keep rotating with family-reuse detection.
  • Offline revocation: mcp-hub-admin clients list|revoke (run against the mounted /data while the hub is stopped) removes a client's approval and refresh tokens and immediately rejects its outstanding access tokens via a revokedBefore marker.
  • Stricter JWT verification: the EdDSA algorithm is pinned and issuer, audience, subject and client_id are validated explicitly.
  • Request limits: cheap per-IP rate limits guard /register, /authorize, /token, /login and /consent before any body parsing; authenticated MCP traffic passes a per-client gate (MCP_REQUESTS_PER_MINUTE, default 120, and MCP_MAX_CONCURRENT_REQUESTS, default 4); the MCP JSON body limit drops to 1 MB (MCP_BODY_LIMIT) and is parsed only after bearer auth; the Node server gets header/request timeouts (HTTP_HEADERS_TIMEOUT_MS, HTTP_REQUEST_TIMEOUT_MS).
  • Browser hardening on the interactive auth pages: CSP with frame-ancestors 'none' and form-action 'self', X-Frame-Options: DENY, nosniff, Referrer-Policy: no-referrer; x-powered-by removed.

Supply chain

  • Base images, the uv helper and every GitHub Action are pinned to digests/commit SHAs; npm installs run with --ignore-scripts.
  • CI gates publishing behind CodeQL, a Trivy scan of both platform images (HIGH/CRITICAL, zero findings) and npm audit; published images ship an SBOM and mode=max provenance. Dependabot watches npm, Docker and Actions weekly.
  • The runtime image replaces the base image's bundled npm 10 with npm 12 and patches its two remaining vendored CVEs (brace-expansion, ip-address) in place.
  • The compose example now runs with a read-only root filesystem, explicit tmpfs mounts and all capabilities dropped.

Breaking / behavioral changes

  • /health (per-server status) now requires a bearer token. The new unauthenticated /livez answers liveness only; the image HEALTHCHECK uses it, and external monitoring should too. livez joins the reserved server names.
  • Access tokens last 15 minutes — clients must use the refresh flow (Claude Web and Claude Code do).
  • Enabling RESOURCE_BOUND_TOKENS=true invalidates previously issued global access/refresh tokens; each client re-authorizes once.
  • curl was removed from the image and tini is now PID 1.
  • Install stdio server binaries at exact, reviewed versions in a custom image instead of downloading them at runtime via npx -y/uvx — required with the read-only root filesystem and strongly recommended regardless (see SECURITY.md).

v0.2.0

Choose a tag to compare

@ni-c ni-c released this 11 Aug 17:41
v0.2.0
a457c7a

Added

  • LOG_FILE: mirrors every log line into a file (ISO-8601 UTC prefix per line) while leaving the console untouched, so docker logs keeps working. Gives log followers such as fail2ban a stable path — the Docker json-file path contains the container ID and changes on every recreate, and the journald driver maps all stderr to priority err, which makes every ordinary line of an MCP server (stdout is reserved for the protocol) look like a system error. Only the hub's own lines are mirrored; stdio children inherit stderr and stay in the container log.

The README documents the matching fail2ban filter and why bans belong in the DOCKER-USER chain.

v0.1.0

Choose a tag to compare

@ni-c ni-c released this 11 Aug 13:53
v0.1.0
50f5589

First public release of mcp-hub — serve many stdio MCP servers from one container, published over HTTPS for Claude Web custom connectors, Claude Code and any other Streamable-HTTP MCP client.

Highlights

  • Config is exactly Claude Code's mcpServers format — copy entries 1:1 into /config/mcp.json.
  • Path-based routing: one endpoint per server (/<name>, /<name>/mcp).
  • /hub aggregate: register a single connector and reach every server through 4 meta-tools (list_servers, list_tools, get_tool_schema, call_tool) instead of flooding the model context with N×tool schemas.
  • Built-in OAuth 2.1 authorization server: dynamic client registration, PKCE, single-password login, explicit per-client approval, rotating refresh tokens.
  • Supervision: stdio children are spawned at boot, pinged and restarted with exponential backoff; a down server answers 503 instead of hanging. Remote http/sse upstreams are supported natively with static headers.
  • Hot reload: edits to mcp.json start/stop/restart only the affected servers.
  • Stateless Streamable HTTP and no database — state is one JSON file plus a JWT key under /data.
  • Runs non-root (uid 1000), no-new-privileges, login rate limiting with fail2ban-friendly log lines.

Install

docker pull ghcr.io/ni-c/mcp-hub:0.1.0

Multi-arch: linux/amd64 and linux/arm64. Tags: 0.1.0, 0.1, latest (tip of main) and sha-<commit>.

See the README for configuration, the environment variables (EXTERNAL_URL, PASSWORD_HASH, TRUSTED_PROXIES, …) and reverse-proxy requirements.