Portal
Provides authentication integration with the lab's Keycloak OIDC provider, allowing members to sign in to the portal without passwords and enabling MCP tokens to act with the signed-in member's permissions.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
██████╗ ██████╗ ██████╗ ████████╗ █████╗ ██╗
██╔══██╗██╔═══██╗██╔══██╗╚══██╔══╝██╔══██╗██║
██████╔╝██║ ██║██████╔╝ ██║ ███████║██║
██╔═══╝ ██║ ██║██╔══██╗ ██║ ██╔══██║██║
██║ ╚██████╔╝██║ ██║ ██║ ██║ ██║███████╗
╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝WinLab Portal
The lab's internal apps on one Postgres: sign in with Keycloak, and everything you can click is also an MCP tool.
nextjs · postgres · docker · mcp
WinLab members book rooms, file receipts, sign documents and open the lab door through one portal. This is its rewrite: plain Postgres instead of a hosted backend, one app at a time, and every action an agent can call as well as a member can click.
> "Who am I on the portal?"
⚡ whoami {}
✓ { "name": "王小明", "username": "ming", "email": "ming@example.com" }What it does
Signs members in with the lab's Keycloak (OIDC); there are no passwords here.
Defines each action once: a page and its MCP tool run the same code, so neither can drift.
Serves MCP at
/mcp, with the portal itself as the OAuth 2.1 authorization server (Client ID Metadata Documents, plus dynamic registration for older clients).
Related MCP server: eq-mcp-gateway
Deploy
With Docker Compose, on any machine with Docker:
curl -fsSLO https://raw.githubusercontent.com/NYCU-WinLab/portal/main/compose.yaml
curl -fsSL -o .env https://raw.githubusercontent.com/NYCU-WinLab/portal/main/.env.example
# set POSTGRES_PASSWORD, BETTER_AUTH_URL, BETTER_AUTH_SECRET and the KEYCLOAK_* keys in .env
docker compose up -dThis starts Postgres, runs the migrations once, then serves the portal from ghcr.io/nycu-winlab/portal on 127.0.0.1:3000.
Put a reverse proxy with TLS in front, at the host inBETTER_AUTH_URL. MCP clients only accept an HTTPS resource, and the Keycloak redirect URI must match it.
portal.winlab.tw deploys on every push to main. The release workflow pushes the image, then sends a Carrel app release (winfra/portal). On the machine, carrel-deployd runs deploy/carrel-start.sh: it sets PORTAL_VERSION in /opt/winlab-portal/.env and waits until web is healthy. A failed health check rolls back to the previous release. The app unit has a drop-in with Type=notify, NotifyAccess=all and TimeoutStartSec=300, so the check waits for the new container.
Use
In your Keycloak realm, create a confidential OpenID Connect client with the redirect URI
<BETTER_AUTH_URL>/api/auth/callback/keycloak, and put its ID and secret in.env.Open
BETTER_AUTH_URLand sign in.Make the first portal admin, once, after that member has signed in (later admins are added on /admins):
docker compose exec postgres psql -U portal -d portal -c \ "insert into admins (user_id, app) select id, 'portal' from users where username = '<their account>'"Add the MCP server to a client, for example
claude mcp add --transport http portal <BETTER_AUTH_URL>/mcp, approve it on the consent page, then ask it to callwhoami.
Configure
Set these in .env; .env.example documents every one.
Key | What it sets | Default |
| The database password, used by every service | required |
| The public URL; the MCP resource is | required |
| Signs sessions and OAuth queries | required |
| The realm URL, e.g. | required |
| The portal's Keycloak client | required |
| Image tag |
|
| Where web listens on the host |
|
| OTLP/HTTP endpoint for traces and error logs; off when empty | empty |
How it works
flowchart LR
member[Member] -->|browser| pages[Pages]
agent[MCP client] -->|bearer token| mcp["/mcp"]
pages --> actions[Actions]
mcp --> actions
actions --> pg[(Postgres)]
member -->|sign in| kc[Keycloak]
mcp -. verifies against .-> as[Portal OAuth server]Keycloak proves who a member is; the portal keeps its own session and is the authorization server for MCP, so the lab-wide realm never opens client registration. An MCP token carries the member's id and acts with exactly their permissions. Only lib/actions, lib/auth and lib/db may touch the database, and CI checks that every action is in the registry the MCP tools are built from.
Develop
bun install
cp .env.example .env.local # point DATABASE_URL at a local Postgres
bun run db:migrate
bun run devCI runs typecheck, lint, format, the design token check, the action registry check and a build, then builds the image and probes a real docker compose up. Schema changes go through bun run db:generate; see CLAUDE.md for the conventions.
Limitations
Only the sign-in, member record and MCP surface exist so far; the apps move over from portal.winlab.tw one at a time.
One instance: DPoP replay records are in Postgres, but nothing else has been tried with more than one web container.
Contributing
Issues and PRs welcome: start with CONTRIBUTING.md.
License
MIT · made in a lab whose door has its own MCP tool
This server cannot be deployed
Maintenance
Related MCP Connectors
Appreciate teammates, celebrate milestones, and run workspace ops from MCP clients via OAuth.
Managed Postgres MCP: projects, SQL, docs search, and storage buckets via OAuth.
Managed MCP gateway with OAuth, per-agent permissions, shared accounts and activity logs.
Hosted MCP server with managed OAuth for 15+ toolkits: Google Workspace, Fitbit, Oura, Kalshi, etc.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables AI clients to securely access, query, and mutate normalized user-controlled health data (e.g., from Apple Health or Supabase) through a bounded set of MCP tools, with optional OAuth and sandboxed deployment.MIT

eq-mcp-gatewayofficial
FlicenseNot gradedqualityBmaintenanceA remote MCP server that lets MCP clients self-register over OAuth 2.1 and call read-only tools for organization identity, place and region browsing, dashboards, metrics, and ranking, forwarding the caller's own Auth0 token so each service still sees the real user. It also exposes a bearer pass-through surface for first-party apps holding an existing token.-- AlicenseNot gradedqualityBmaintenanceEnables database querying and modification through an MCP server where each action is gated by human-granted scopes, per-call confirmations for destructive operations, and revocable access.MIT
- AlicenseNot gradedqualityCmaintenanceEnables any MCP client to read and edit database schemas (DBML/SQL), Mermaid diagrams, and shared board layouts, along with the organizations, projects, documents, and marketplace listings around them. It runs as a hosted OAuth 2.1 endpoint, so there is nothing to install and access is limited to what the signed-in user can already see.MIT