v0.4.0 — OAuth + Streamable HTTP
A feature release adding OAuth per-connection authentication and the MCP Streamable HTTP transport. Backward compatible — PAT mode and stdio/SSE transports continue to work unchanged.
✨ Added
- OAuth per-connection authentication (
AUTH_MODE=oauth): newcreateMcpServer(token)factory creates isolatedServer+GitLabApiinstances per connection using the Bearer token from theAuthorizationheader. PAT mode (default) is unchanged. - Streamable HTTP transport (
USE_STREAMABLE_HTTP=true): implements the MCP Streamable HTTP spec onPOST/GET/DELETE /mcpwithMCP-Session-Idsession management. Cross-protocol session-id collisions and unknown sessions return 400 JSON-RPC errors. - CORS origin allowlist (
CORS_ALLOW_ORIGINS): OAuth mode default-denies browser origins; PAT mode keeps permissive*for local dev.Vary: Originset when echoing. /healthzendpoint with active session count and configurable threshold (HEALTHZ_MAX_SESSIONS, default10000); returns503with{"status":"unhealthy","reason":"session_limit_exceeded","sessions":<n>}when exceeded — meaningful signal for Kubernetes probes.AUTH_MODEstartup validation: invalid values exit withprocess.exit(1)and a clear message.- 17 new vitest cases covering Bearer extraction, Streamable HTTP lifecycle, cross-protocol collision,
/healthz, and CORS handling. Total: 58 tests pass. docs/OPERATIONS.md— operations guide (K8s probes, env var reference, troubleshooting).
🔧 Changed
src/transport.tsreorganized with helper functions for clarity + testability.- Memory-leak hardening on Streamable HTTP
connect()failure (initializedSidcapture + best-effortclose()+ idempotenttransports[sid] === transportcleanup). - Legacy SSE cleanup is now idempotent and registered on both
req.closeandtransport.onclose; transport map entry created only after successfulconnect().
🔐 Provenance
Published with npm Trusted Publishing — Sigstore-signed SLSA v1 provenance attestation. Verify with npm view @yoda.digital/gitlab-mcp-server@0.4.0 dist.attestations.
👏 Credits
- Implementation: @ecthelion77 (Olivier Gintrand)
- Maintainer rebase fixup + release packaging: @nalyk
- Reviewed via #28 → merged via #42
Full notes: CHANGELOG.md.